题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3371
题目大意:给你很多条边,包括顶点和权值。再给你一些点,表示这些点已经有图连通,求最小生成树的权值之和。
解题思路:
将后来的连通的边的权值设定为0就可以了。就是比较裸的最小生成树。。。但是细节处理比较麻烦,我就是处理后来那些连通顶点花了很长时间,而且是卡过去了。。题目要求1s。我968ms。看来需要优化。。。。。。。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define INF 0x3f3f3f3f #define MAXN 510 int map[MAXN][MAXN], lowcost[MAXN]; bool visit[MAXN]; int alr[MAXN]; int num, sum; void prim() { int temp, k; memset(visit, false, sizeof(visit)); for(int i = 1; i <= num; ++i) lowcost[i] = map[1][i]; sum = 0; visit[1] = true; for(int i = 1; i <= num; ++i) { temp = INF; for(int j = 1; j <= num; ++j) if(!visit[j] && temp > lowcost[j]) temp = lowcost[k = j]; if(temp == INF) break; visit[k] = 1; sum += temp; for(int j = 1; j <= num; ++j) if(!visit[j] && lowcost[j] > map[k][j]) lowcost[j] = map[k][j]; } } int main() { int ncase; int road, already; int a, b, cost; int nodenum, node; bool flag; scanf("%d", &ncase); while(ncase--) { flag = true; memset(alr, INF, sizeof(alr)); memset(map, INF, sizeof(map)); scanf("%d%d%d", &num, &road, &already); for(int i = 1; i <= road; ++i) { scanf("%d%d%d", &a, &b, &cost); if(cost < map[a][b]) map[a][b] = map[b][a] = cost; } for(int i = 1; i <= already; ++i) //处理这些权值为0的边 { scanf("%d", &nodenum); for(int j = 1; j <= nodenum; ++j) scanf("%d", &alr[j]); int k; for(int j = 1; j < nodenum; ++j) { k = j + 1; map[alr[j]][alr[k]] = map[alr[k]][alr[j]] = 0; } } prim(); for(int i = 1; i <= num; ++i) //判断图的连通性 if(visit[i] == false) flag = false; if(flag) printf("%d\n", sum); else printf("-1\n"); } return 0; }