Problem Description省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
Input测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
Output对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
Sample Input3 31 2 11 3 22 3 41 32 3 20 100
Sample Output3?
Source
RecommendAC代码:
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int MAX=1e6+10; int m,n; int par[MAX]; int pos[MAX]; int Max; struct tree { int x,y; int pow; }tre[MAX]; int cmp(tree a,tree b) { return a.pow<b.pow; } void init(int n) { for(int i=0;i<n;i++) par[i]=i,pos[i]=1; } int find(int x) { int p=x; while(x!=par[x]) x=par[x]; while(par[p]!=x) { int j=par[p]; par[p]=x; p=j; } return x; } void unite(int a,int b) { int fa=find(a); int fb=find(b); if(fa!=fb) { par[fa]=fb; pos[fb]+=pos[fa]; //if(pos[fb]>Max) Max=pos[fb];//统计节点个数 } } void kruskal() { int sumweight=0;//统计总权的大小 int num=0; int u,v; init(m); for(int i=0;i<m;i++) { u=tre[i].x; v=tre[i].y; if(find(u)!=find(v))//如果他俩不在一个集合中合并 并 统计他们的权重和 { sumweight+=tre[i].pow; num++; unite(u,v); } } if(Max==m) //如果统计的节点个数等于输入的节点个数说明可以形成最小生成树 printf("%d\n",sumweight); //否则则不能 else printf("?\n"); } int main() { while(scanf("%d%d",&n,&m),n) { Max=1; memset(tre,0,sizeof(tre));//初始化数组 否则会出现某些bug for(int i=0;i<n;i++) scanf("%d%d%d",&tre[i].x,&tre[i].y,&tre[i].pow); sort(tre,tre+m,cmp);//排序由权重从小到大排序 kruskal(); } return 0; }