Special minimum spanning tree - c++14

There is a node that can only get one line, I use both kruskal and prim, but the judger said TLE(Time Limit Exceed).
Then I will describe the question. There are many computers, we need to connect all of them, we give the cost of connection between different computers, also we give the special number of computer which can be only connected by one line. Finally, we guarantee there is a answer and there is no Self-Loop, but there may have multiple edge which have different weight between same node.
Here is my kruskal code, it's TLE.
#include <iostream>
#include <algorithm>
using namespace std;
typedef struct edge{
int start;
int end;
int weight;
}Edge;
int special = 0;
int edgenum;
Edge _edge[600005];
int i, j, k;
int counter = 0;
bool Cmp(const edge &a, const edge &b){
return a.weight < b.weight;
}
int getEnd(int vends[], int i){
while(vends[i] != 0)
i = vends[i];
return i;
}
void kruskal(){
int p1, p2, m, n, ans = 0;
int vends[10005] = {0};
sort(_edge, _edge+counter, Cmp);
for(i = 0; i < edgenum; ++i){
p1 = _edge[i].start;
p2 = _edge[i].end;
if ((p1 == k || p2 == k) && special)
continue;
m = getEnd(vends, p1);
n = getEnd(vends, p2);
if(m != n){
if (p1 == k || p2 == k)
special = 1;
vends[m] = n;
ans += _edge[i].weight;
}
}
cout << ans << endl;
}
int main(){
int n, m;
cin >> n >> m >> k;
edgenum = m;
while(m--){
int a, b, c;
cin >> a >> b >> c;
_edge[counter].start = a; //Get the Edge
_edge[counter].weight = c;
_edge[counter++].end = b;
// _edge[counter].start = b;
// _edge[counter].weight = c;
// _edge[counter++].end = a;
}
kruskal();
}
Here is my Prim, but also TLE:
#include <iostream>
using namespace std;
typedef char VertexType;
typedef struct node{
int adjvex = 0;
int weight = INT32_MAX;
struct node *next = NULL;
}Node;
typedef struct vnode{
VertexType data;
Node *firstnode = NULL;
}Vnode;
Vnode node[10005];
int VNUM;
int n, m, k;
int lowcost[10005] = {0};
int addvnew[10005]; //未加入最小生成树表示为-1,加入则为0
int adjecent[10005] = {0};
bool is_special = false;
int flag;
void prim(int start){
long long sumweight = 0;
int i, j;
Node *p = node[start].firstnode;
for (i = 1; i <= VNUM; ++i) { //重置
addvnew[i] = -1;
}
while (p->next != NULL){
if (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])
lowcost[p->adjvex] = p->weight;
p = p->next;
}
if (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])
lowcost[p->adjvex] = p->weight;
addvnew[start] = 0;
// adjecent[start] = start;
if (start == k) {
is_special = true;
flag = 1;
}
for (i = 1; i < VNUM; ++i) {
int min = INT32_MAX;
int v=-1;
for (j = 1; j <= VNUM; ++j) { //Find the min
if (addvnew[j] == -1 && lowcost[j] < min && lowcost[j] != 0){
min = lowcost[j];
v = j;
}
}
if (v != -1){ //if min is found
if (flag == 1){
for (int l = 0; l < 10005; ++l) {
lowcost[l] = 0;
}
flag = 0;
}
addvnew[v] = 0;
sumweight += min;
p = node[v].firstnode;
while(p->next != NULL){
if (is_special && p->adjvex == k){ //If find the special node
p = p->next;
continue;
}
if(addvnew[p->adjvex] == -1 && (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])){ //如果该点未连接
lowcost[p->adjvex] = p->weight;
}
p = p->next;
}
if (!(is_special && p->adjvex == k))
if(addvnew[p->adjvex] == -1 && (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])){
lowcost[p->adjvex] = p->weight;
}
}
}
cout << sumweight << endl;
}
int main(){
cin >> n >> m >> k;
VNUM = n;
while (m--){
int a, b, c;
cin >> a >> b >> c;
Node *p = (Node*)malloc(sizeof(Node));
p->adjvex = b;
p->weight = c;
p->next = node[a].firstnode;
node[a].firstnode = p;
Node *q = (Node*)malloc(sizeof(Node));
q->adjvex = a;
q->weight = c;
q->next = node[b].firstnode;
node[b].firstnode = q;
}
prim(k);
}
I don't know how to modify the both code, I try my best, thank you

Related

CSES Dynamic Range Minimum Queries

https://cses.fi/problemset/task/1649
I'm solving this problem using Segment Trees and the solution I've written is
#include <bits/stdc++.h>
#define MAX 1000000001
using namespace std;
int n;
vector<int> tree;
int sum(int a, int b)
{
a += n;
b += n;
int s = INT_MAX;
while(a <= b) {
if (a % 2 == 1) s = min(s, tree[a++]);
if (b % 2 == 0) s = min(s, tree[b--]);
a>>=1;
b>>=1;
}
return s;
}
void update(int k, int change)
{
k += n;
tree[k] = change;
for(int i = k>>1; i >= 1; i>>=1) {
tree[i] = min(tree[2*i], tree[2*i+1]);
}
return;
}
int main()
{
int q;
cin >> n >> q;
n = pow(2, ceil(log2(n)));
tree.resize(2*n, INT_MAX);
for(int i = 0; i < n; i++) {
cin >> tree[i+n];
}
for(int i = n-1; i >= 1; i--) {
tree[i] = min(tree[2*i], tree[2*i+1]);
}
int type, a, b;
for(int i = 0; i < q; i++) {
cin >> type >> a >> b;
if (type == 1) {
update(a-1, b);
} else {
cout << sum(a-1, b-1) << endl;
}
}
return 0;
}
It works with first test case, but not with the second one. I've looked at other solutions online and they all look similar to mine. Please, help me spot the mistake.

Why do I keep getting TLE for POJ 1984 -- Navigation Nightmare?

#include <iostream>
#include <vector>
#include <cassert>
#include <queue>
using namespace std;
struct vectors{
int x;
int y;
bool visited;
vectors(int x = 0, int y = 0){
this -> x = x;
this -> y = y;
visited = false;
}
bool isNotFound(){
return visited == false;
}
void setZero(){
x = 0;
y = 0;
}
vectors operator+(vectors others){
return vectors(x + others.x, y + others.y);
}
vectors operator*(int others){
return vectors(x * others, y * others);
}
};
struct node{
int adjFarm;
int length;
char direction;
node(int f, int l, char d){
adjFarm = f;
length = l;
direction = d;
}
};
int num_villages;
char inverse_direction(char d){
assert(d == 'N' || d == 'E' || d == 'W' || d == 'S' );
switch(d){
case 'S': return 'N';
case 'N': return 'S';
case 'E': return 'W';
case 'W': return 'E';
}
}
void AddToPaths(int farm1, int farm2, char direction, int length, vector< vector<node> > &pathGraph){
pathGraph.at(farm1).push_back(node(farm2, length, direction));
pathGraph.at(farm2).push_back(node(farm1, length, inverse_direction(direction)));
}
vectors directionVector(int d){
switch(d){
case 'N': return vectors(0, 1);
case 'E': return vectors(1, 0);
case 'W': return vectors(- 1, 0);
case 'S': return vectors(0, - 1);
}
}
void print_coords(vector< vectors > coords){
for(int i = 1; i < num_villages + 1; i ++){
cout << "farm: " << i << " coordinates x at farm: " << coords.at(i).x << " coordinated y at farm: " << coords.at(i).y << endl;
}
}
void update(char direction, int newFarm, int length, int currentFarm, vector <vectors> &coords){
vectors directions = directionVector(direction);
coords.at(newFarm) = coords.at(currentFarm) + directions * length;
coords.at(newFarm).visited = true;
}
void computeCoords(vector <vectors> &coords, vector< vector<node> > &pathGraph){
queue <int> frontier;
frontier.push(1);
coords.at(1).visited = true;
while(!frontier.empty()){
int currentFarm = frontier.front();
frontier.pop();
for(int i = 0; i < pathGraph.at(currentFarm).size(); i ++){
node options = pathGraph.at(currentFarm).at(i);
if(coords.at(options.adjFarm).isNotFound()){
update(options.direction, options.adjFarm, options.length, currentFarm, coords);
frontier.push(options.adjFarm);
}
}
}
}
struct UnionFind{
vector<int> L;
UnionFind(int num_villages){
L.resize(num_villages + 1);
for(int i = 1; i <= num_villages; i ++){
L.at(i) = i;
}
}
int find(int x){
if(x == L.at(x)) return x;
int root = find(L.at(x));
L.at(x) = root;
return root;
}
int Union(int x, int y){
int root1 = find(x);
int root2 = find(y);
L.at(y) = root1;
}
};
int pos;
int query(int start, int destination, int order, UnionFind &reachables, vector<vectors> &coords, vector<vector<int> > &source_destination_order){
while(pos <= order){
reachables.Union(reachables.find(source_destination_order.at(pos).at(0)), reachables.find(source_destination_order.at(pos).at(1)));
pos ++;
}
if(reachables.find(start) == reachables.find(destination)){
return abs(coords.at(start).x - coords.at(destination).x) + abs(coords.at(start).y - coords.at(destination).y);
}
else{
return -1;
}
}
int main(void){
int num_roads;
cin >> num_villages;
cin >> num_roads;
vector <vector<node> > pathGraph(num_villages + 1);
vector <vectors > coords(num_villages + 1);
vector <vector <int> > source_destination_order(num_villages + 1, vector<int> (2));
//Adding inforamtion about the farms
int farm1;
int farm2;
char direction;
int length;
int source;
for(int i = 0; i < num_roads; i ++){
cin >> farm1;
cin >> farm2;
cin >> length;
cin >> direction;
AddToPaths(farm1, farm2, direction, length, pathGraph);
source_destination_order.at(i + 1).at(0) = farm1;
source_destination_order.at(i + 1).at(1) = farm2;
}
computeCoords(coords, pathGraph);
int numQueries;
cin >> numQueries;
int start;
int destination;
int order;
int result;
UnionFind reachables(num_villages);
pos = 1;
for(int i = 0; i < numQueries; i ++){
cin >> start;
cin >> destination;
cin >> order;
result = query(start, destination, order, reachables, coords, source_destination_order);
cout << result << endl;
}
}
I tried to create an undirected acyclic graph with the farms as the vertices and the roads as the edges, and then use BFS to compute the coordinates of each farm relative to the first farm. Afterwards I used the union find structure to create disjoint sets of farms that are reachable from each other at the time of the query. However, it seems like my code takes too long to run, how should I fix it?

Codechef GALACTIK solution

Here's the link for the problem:
I have used union-find algorithm to solve the problem.
Code:
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
#define INT 100000000
unordered_map<ll, ll> parent;
unordered_map<ll, ll> depth;
std::vector<ll> cost;
ll find_set(ll x) {
if (x == parent[x])return x;
parent[x] = find_set(parent[x]);
return parent[x];
}
void union_set(ll x, ll y) {
/*
Creating a disjoint set such that the node with smallest cost
being the root using union-rank concept.
*/
ll rep1 = find_set(x), rep2 = find_set(y);
if (depth[rep1] > depth[rep2])parent[rep1] = rep2;
else if (depth[rep2] >= depth[rep1])parent[rep2] = rep1;
}
int main() {
ll n, m;
cin >> n >> m;
ll c[m + 1][3];
for (ll i = 1; i <= m; i++) {
cin >> c[i][1] >> c[i][2]; //Accepting the edges
}
for (ll i = 1; i <= n; i++) {
parent[i] = i;
cin >> depth[i];
if (depth[i] < 0)depth[i] = INT;
/*we assume that each negative cost is replaced by a very
large positive cost.*/
}
for (ll i = 1; i <= m; i++) {
union_set(c[i][1], c[i][2]);
}
set<ll> s;
std::vector<ll> v;
//storing representatives of each connected component
for (auto i = 1; i <= n; i++)s.insert(depth[find_set(i)]);
for (auto it = s.begin(); it != s.end(); it++)v.push_back(*it);
sort(v.begin(), v.end());
if (s.size() == 1) {
//Graph is connected if there is only 1 connected comp
cout << 0 << endl;
return 0;
}
bool flag = false;
ll p = 0;
for (ll i = 1; i < v.size(); i++) {
if (v[i] == INT) {
flag = true;
break;
}
p += (v[0]+v[i]);
}
if (flag)cout << -1 << endl;
else cout << p << endl;
return 0;
}
Logic used in my program:
To find the answer, take the minimum value of all the valid values in a connected component.Now to make the graph connected, Take the minimum value of all the values we got from the above step and make edge from that node to all the remaining nodes.If graph is already connected than answer is 0.if there exists a connected component where all nodes are not valid to be chosen, than answer is not possible (-1).
But this solution is not accepted?What's wrong with it?

How to modify algorithm to get all maximal matchings in bipartite graph?

I use the following code to find maximal matching in bipartite graph
(I've tried to add a few comments):
#include <iostream>
using namespace std;
// definition of lists elements
//-------------------------------
struct slistEl
{
slistEl * next;
int data;
};
// definition objective type queue
//---------------------------------
class queue
{
private:
slistEl * head;
slistEl * tail;
public:
queue();
~queue();
bool empty(void);
int front(void);
void push(int v);
void pop(void);
};
queue::queue()
{
head = tail = NULL;
}
queue::~queue()
{
while(head) pop();
}
bool queue::empty(void)
{
return !head;
}
int queue::front(void)
{
if(head) return head->data;
else return -10000;
}
void queue::push(int v)
{
slistEl * p = new slistEl;
p->next = NULL;
p->data = v;
if(tail) tail->next = p;
else head = p;
tail = p;
}
void queue::pop(void)
{
if(head)
{
slistEl * p = head;
head = head->next;
if(!head) tail = NULL;
delete p;
}
}
//---------------
// main part
//---------------
queue Q; // queue
int *Color; // colors of vertexes
slistEl **graf; // adjacency array
int **C; // matrix of capacity
int **F; // matrix of nett flow
int *P; // array of prev
int *CFP; // array of residual capacity
int n,m,fmax,cp,v,u,i,j; //
bool esc; //
slistEl *pr, *rr; // pointer for list elements
int main(int argc, char *argv[])
{
// n - number of vertexes
// m - number of edges
cin >> n >> m;
Color = new int [n];
graf = new slistEl * [n];
for(i = 0; i < n; i++)
{
graf[i] = NULL;
Color[i] = 0;
}
C = new int * [n+2];
F = new int * [n+2];
for(i = 0; i <= n + 1; i++)
{
C[i] = new int [n+2];
F[i] = new int [n+2];
for(j = 0; j <= n + 1; j++)
{
C[i][j] = 0;
F[i][j] = 0;
}
}
P = new int [n+2];
CFP = new int [n+2];
// reading edges definition and adding to adjacency list
for(i = 0; i < m; i++)
{
cin >> v >> u;
pr = new slistEl;
pr->data = u;
pr->next = graf[v];
graf[v] = pr;
pr = new slistEl;
pr->data = v;
pr->next = graf[u];
graf[u] = pr;
}
for(i = 0; i < n; i++){
cin>> Color[i];
}
for(i = 0; i < n; i++)
if(Color[i] == -1)
{
for(pr = graf[i]; pr; pr = pr -> next) // neighbours of blue
C[i][pr->data] = 1; // capacity to red
C[n][i] = 1; // capacity to source
}
else C[i][n+1] = 1; // capacity edges to outfall
//** Edmonds-Karp algorithm **
fmax = 0;
while(true)
{
for(i = 0; i <= n + 1; i++) P[i] = -1;
P[n] = -2;
CFP[n] = MAXINT;
while(!Q.empty()) Q.pop();
Q.push(n);
esc = false;
while(!Q.empty())
{
v = Q.front(); Q.pop();
for(u = 0; u <= n + 1; u++)
{
cp = C[v][u] - F[v][u];
if(cp && (P[u] == -1))
{
P[u] = v;
if(CFP[v] > cp) CFP[u] = cp; else CFP[u] = CFP[v];
if(u == n+1)
{
fmax += CFP[n+1];
i = u;
while(i != n)
{
v = P[i];
F[v][i] += CFP[n+1];
F[i][v] -= CFP[n+1];
i = v;
}
esc = true; break;
}
Q.push(u);
}
}
if(esc) break;
}
if(!esc) break;
}
// showing reuslts
if(fmax > 0)
for(v = 0; v < n; v++)
for(u = 0; u < n; u++)
if((C[v][u] == 1) && (F[v][u] == 1))
cout << v << " - " << u << endl;
cout << endl;
// cleaning
delete [] Color;
for(i = 0; i < n; i++)
{
pr = graf[i];
while(pr)
{
rr = pr;
pr = pr->next;
delete rr;
}
}
delete [] graf;
for(i = 0; i <= n + 1; i++)
{
delete [] C[i];
delete [] F[i];
}
delete [] C;
delete [] F;
delete [] P;
delete [] CFP;
return 0;
}
It returns only one maximal matching. For example for data:
6 7
0 3 0 5
1 3 1 4 1 5
2 3 2 5
1 1 1 -1 -1 -1
But there are more maximal matchings.
I don't know, how should I modify it to get all results and I would like to ask somebody for help. Thank you in advance.
That algorithm is only efficient to get you a maximum matching.
If you want all maximal matching you have to consider the case where any matching is a maximal matching. In that case you have N! possibilities.
Since you will need to visit all solutions your complexity will be O(N!) at least. Therefore, forget the code you have, you can just try all possible matchings using a recursive algorithm and keep the set of maximal matching you get.

Unable to find a wrong answer testcase for spoj MMINPAID

Problem link : http://www.spoj.com/problems/MMINPAID/
Getting WA on submitting.
I have used bfs to reach Nth node and calculating minimum cost for nodes in a path using bitmask. However after running on a huge number of testcases and comparing with an accepted solution, not able to find a failure testcase.
Code:
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int MAXN = 15, INF = 1 << 29;
struct node {
int c, p, r;
};
struct node data[MAXN][MAXN];
vector<int> g[MAXN];
int N, M, dist[MAXN][1 << 11];
int bfs() {
for (int i = 0; i < MAXN; i++)
for (int k = 0; k < (1 << 11); k++)
dist[i][k] = INF;
queue< pair< pair <int, int> , int > > q;
int v = 1, path = (1 << 1), cost = 0;
dist[v][path] = 0;
q.push(make_pair(make_pair(v, path), cost));
while (!q.empty()) {
int curv = q.front().first.first;
int curpath = q.front().first.second;
int curcost = q.front().second;
q.pop();
for (int i = 0; i < g[curv].size(); i++) {
int nv = g[curv][i];
int d1 = curcost + data[curv][nv].r;
int d2 = INF;
if (curpath & (1 << data[curv][nv].c)) {
d2 = curcost + data[curv][nv].p;
}
int d3 = min(d1, d2);
int npath = curpath | (1 << nv);
if (d3 < dist[nv][npath]) {
dist[nv][npath] = d3;
q.push(make_pair(make_pair(nv, npath), d3));
}
}
}
int res = INF;
for (int i = 0; i < (1 << 11); i++) {
res = min(res, dist[N][i]);
}
return res;
}
int main() {
scanf("%d %d", &N, &M);
for (int i = 0; i < M; i++) {
int a, b, c, p, r;
scanf("%d %d %d %d %d", &a, &b, &c, &p, &r);
g[a].push_back(b);
data[a][b] = (struct node) {c, p, r};
}
int ret = bfs();
if (ret == INF) printf("impossible\n");
else printf("%d\n", ret);
return 0;
}
I think the problem might be that your data[a][b] structure assumes there is at most a single road from a to b.
However, the problem states:
There may be more than one road connecting one city with another.

Resources