并查集+最小生成树
畅通工程
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 19824 Accepted Submission(s):
8449
Problem Description
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
Input
测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100
);随后的 N
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
Output
对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
Sample Input
3 3
1 2 1
1 3 2
2 3 4
1 3
2 3 2
0 100
Sample Output
3
?
附上两种算法
kruskal算法
#include<stdio.h> #include<algorithm> using namespace std; int set[110]; struct record { int beg; int end; int money; }s[11000]; int find(int fa) { int ch=fa; int t; while(fa!=set[fa]) fa=set[fa]; while(ch!=fa) { t=set[ch]; set[ch]=fa; ch=t; } return fa; } void mix(int x,int y) { int fx,fy; fx=find(x); fy=find(y); if(fx!=fy) set[fx]=fy; } bool cmp(record a,record b) { return a.money<b.money; } int main() { int city,road,n,m,j,i,sum; while(scanf("%d",&road)&&road!=0) { scanf("%d",&city); for(i=0;i<road;i++) { scanf("%d%d%d",&s[i].beg,&s[i].end,&s[i].money); } for(i=1;i<=city;i++) set[i]=i; sort(s,s+road,cmp); sum=0; for(i=0;i<road;i++) { if(find(s[i].beg)!=find(s[i].end)) { mix(s[i].beg,s[i].end); sum+=s[i].money; } } j=0; for(i=1;i<=city;i++) { if(set[i]==i) j++; if(j>1) break; } if(j>1) printf("? "); else printf("%d ",sum); } return 0; }
prime算法
#include<stdio.h> #include<string.h> #define INF 0x3f3f3f int lowcost[110];//此数组用来记录第j个节点到其余节点最少花费 int map[110][110];//用来记录第i个节点到其余n-1个节点的距离 int visit[110];//用来记录最小生成树中的节点 int city; void prime() { int min,i,j,next,mincost=0; memset(visit,0,sizeof(visit));//给最小生成树数组清零 for(i=1;i<=city;i++) { lowcost[i]=map[1][i];//初始化lowcost数组为第1个节点到剩下所有节点的距离 } visit[1]=1;//选择第一个点为最小生成树的起点 for(i=1;i<city;i++) { min=INF; for(j=1;j<=city;j++) { if(!visit[j]&&min>lowcost[j])//如果第j个点不是最小生成树中的点并且其花费小于min { min=lowcost[j]; next=j;//记录下此时最小的位置节点 } } if(min==INF) { printf("? "); return ; } mincost+=min;//将最小生成树中所有权值相加 visit[next]=1;//next点加入最小生成树 for(j=1;j<=city;j++) { if(!visit[j]&&lowcost[j]>map[next][j])//如果第j点不是最小生成树中的点并且此点处权值大于第next点到j点的权值 { lowcost[j]=map[next][j]; //更新lowcost数组 } } } printf("%d ",mincost); } int main() { int road; int j,i,x,y,c; while(scanf("%d%d",&road,&city)&&road!=0) { memset(map,INF,sizeof(map));//初始化数组map为无穷大 while(road--) { scanf("%d%d%d",&x,&y,&c); map[x][y]=map[y][x]=c;//城市x到y的花费==城市y到想的花费 } prime(); } return 0; }