题目地址:点击打开链接
题意:给你一堆城市,然后来了一次海啸,海啸完了还有一些城市是连在一块的,问把所有的城市连在最小的花费是多少
思路:Kruskal算法超了无数发,后来改用prim算法,把海啸过后,连在一块的城市之间的距离设为0即可,用C++提交
AC代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <cstring> #include <climits> #include <cmath> #include <cctype> using namespace std; const int maxn = 510; const int zui = 0x3f3f3f3f; int lowdist[maxn]; int map1[maxn][maxn]; int visit[maxn]; int n,m,k,sum; bool flag; void Prim() { int i,j,k; memset(visit,0,sizeof(visit)); for(i=1; i<=n; i++) { lowdist[i] = map1[1][i]; } visit[1] = 1; sum = 0; for(i=1; i<n; i++) { int min1 = zui; for(j=1; j<=n; j++) { if(!visit[j] && lowdist[j] < min1) { min1 = lowdist[j]; k = j; } } if(min1 == zui) { flag = false; return; } visit[k] = 1; sum += lowdist[k]; for(j=1; j<=n; j++) { if(!visit[j] && map1[k][j] < lowdist[j]) { lowdist[j] = map1[k][j]; } } } } int main() { int t; int i,j; scanf("%d",&t); while(t--) { flag = true; memset(map1,zui,sizeof(map1)); scanf("%d%d%d",&n,&m,&k); int p,q,c; for(i=1; i<=m; i++) { scanf("%d%d%d",&p,&q,&c); if(c < map1[p][q]) { map1[p][q] = map1[q][p] = c; } } int l,temp,x; for(i=1; i<=k; i++) { scanf("%d%d",&l,&temp); for(j=1; j<l; j++) { scanf("%d",&x); map1[temp][x] = map1[x][temp] = 0; } } Prim(); if(flag) { printf("%d\n",sum); } else { printf("-1\n"); } } return 0; }
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <cstring> #include <climits> #include <cmath> #include <cctype> using namespace std; const int maxn = 510; const int zui = 1000000000; int lowdist[maxn]; int map1[maxn][maxn]; int visit[maxn]; int n,m,k,sum; bool flag; void Prim() { int i,j,k; memset(visit,0,sizeof(visit)); for(i=1; i<=n; i++) { lowdist[i] = map1[1][i]; } visit[1] = 1; sum = 0; for(i=1; i<n; i++) { int min1 = zui; for(j=1; j<=n; j++) { if(!visit[j] && lowdist[j] < min1) { min1 = lowdist[j]; k = j; } } if(min1 == zui) { flag = false; return; } visit[k] = 1; sum += lowdist[k]; for(j=1; j<=n; j++) { if(!visit[j] && map1[k][j] < lowdist[j]) { lowdist[j] = map1[k][j]; } } } } int main() { int t; int i,j; scanf("%d",&t); while(t--) { flag = true; scanf("%d%d%d",&n,&m,&k); for(i=1; i<=n; i++) { for(j=1; j<=n; j++) { map1[i][j] = zui; } map1[i][i] = 0; } int p,q,c; for(i=1; i<=m; i++) { scanf("%d%d%d",&p,&q,&c); if(c < map1[p][q]) { map1[p][q] = map1[q][p] = c; } } int l,temp,x; for(i=1; i<=k; i++) { scanf("%d%d",&l,&temp); for(j=1; j<l; j++) { scanf("%d",&x); map1[temp][x] = map1[x][temp] = 0; } } Prim(); if(flag) { printf("%d\n",sum); } else { printf("-1\n"); } } return 0; }最后来点Kruskal的超时代码
超时代码1:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <cstring> #include <climits> #include <cmath> #include <cctype> using namespace std; const int maxn = 510; const int zui = 1000000000; int lowdist[maxn]; int map1[maxn][maxn]; int visit[maxn]; int n,m,k,sum; bool flag; void Prim() { int i,j,k; memset(visit,0,sizeof(visit)); for(i=1; i<=n; i++) { lowdist[i] = map1[1][i]; } visit[1] = 1; sum = 0; for(i=1; i<n; i++) { int min1 = zui; for(j=1; j<=n; j++) { if(!visit[j] && lowdist[j] < min1) { min1 = lowdist[j]; k = j; } } if(min1 == zui) { flag = false; return; } visit[k] = 1; sum += lowdist[k]; for(j=1; j<=n; j++) { if(!visit[j] && map1[k][j] < lowdist[j]) { lowdist[j] = map1[k][j]; } } } } int main() { int t; int i,j; scanf("%d",&t); while(t--) { flag = true; scanf("%d%d%d",&n,&m,&k); for(i=1; i<=n; i++) { for(j=1; j<=n; j++) { map1[i][j] = zui; } map1[i][i] = 0; } int p,q,c; for(i=1; i<=m; i++) { scanf("%d%d%d",&p,&q,&c); if(c < map1[p][q]) { map1[p][q] = map1[q][p] = c; } } int l,temp,x; for(i=1; i<=k; i++) { scanf("%d%d",&l,&temp); for(j=1; j<l; j++) { scanf("%d",&x); map1[temp][x] = map1[x][temp] = 0; } } Prim(); if(flag) { printf("%d\n",sum); } else { printf("-1\n"); } } return 0; }
用k判环超时,改用n判环,里面少一个for循环,时间应该少很多
超时代码2:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <cstring> #include <climits> #include <cmath> #include <cctype> using namespace std; int pre[510]; struct node { int left,right,value; }a[25010]; int cmp(const void *_a,const void *_b) { struct node *a = (node*)_a; struct node *b = (node*)_b; return a->value - b->value; } int findroot(int x) { return x == pre[x] ? x : pre[x] = findroot(pre[x]);//求根节点加路径压缩 } int main() { int t,n,m,k; int i,j; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&k); for(i=1; i<=n; i++) { pre[i] = i; } for(i=0; i<m; i++) { scanf("%d%d%d",&a[i].left,&a[i].right,&a[i].value); } qsort(a,m,sizeof(node),cmp); int sum,l,x; int root1,root2; for(i=0; i<k; i++) { scanf("%d",&sum); scanf("%d",&l); root1 = findroot(l); for(j=1; j<sum; j++) { scanf("%d",&x); root2 = findroot(x); if(root1 != root2) { pre[root2] = pre[root1]; n--; } } } sum = 0; for(i=0; i<m; i++) { root1 = findroot(a[i].left); root2 = findroot(a[i].right); if(root1 != root2) { sum += a[i].value; pre[root1] = root2; n--; } if(n == 1) break; } if(n == 1) { printf("%d\n",sum); } else { printf("-1\n"); } } return 0; }用n判环依旧超
超时代码3:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <cstring> #include <climits> #include <cmath> #include <cctype> using namespace std; int pre[510]; struct node { int left,right,value; }a[25010]; int cmp(const void *_a,const void *_b) { struct node *a = (node*)_a; struct node *b = (node*)_b; return a->value - b->value; } int findroot(int x) { return x == pre[x] ? x : pre[x] = findroot(pre[x]);//求根节点加路径压缩 } int main() { int t,n,m,k; int i,j; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&k); for(i=1; i<=n; i++) { pre[i] = i; } for(i=0; i<m; i++) { scanf("%d%d%d",&a[i].left,&a[i].right,&a[i].value); } qsort(a,m,sizeof(node),cmp); int sum,l,x; int root1,root2; for(i=0; i<k; i++) { scanf("%d",&sum); scanf("%d",&l); root1 = findroot(l); for(j=1; j<sum; j++) { scanf("%d",&x); root2 = findroot(x); if(root1 != root2) { pre[root2] = pre[root1]; n--; } } } sum = 0; for(i=0; i<m; i++) { if(pre[a[i].left] != pre[a[i].right]) { pre[pre[a[i].left]] = pre[a[i].right]; sum += a[i].value; n--; } if(n == 1) break; } if(n == 1) { printf("%d\n",sum); } else { printf("-1\n"); } } return 0; }减少函数调用依旧超时