链接: http://acm.hdu.edu.cn/showproblem.php?pid=1879
最小生成树,相较【1233 还是畅通工程】多了一个此路是否已建成的条件,只需把已建成的路的权值置零即可,Prim和Kruskal
Prim:(390MS)
#include <cstdio> #include <climits> #include <cstring> using namespace std; bool used[101]; int map[101][101]; int Prim(int n) { int sum=0; int t,T=n-1,mini; while(T--) { mini=INT_MAX; for(int i=2; i<=n; i++) if(!used[i] && mini>map[1][i]) { mini=map[1][i]; t=i; } used[t]=1; sum+=mini; for(int i=2; i<=n; i++) if(!used[i] && map[t][i]<map[1][i]) map[1][i]=map[t][i]; } return sum; } int main() { int n; while(~scanf("%d",&n),n) { int i,j,dis,b,T=n*(n-1)/2; while(T--) { scanf("%d %d %d %d",&i,&j,&dis,&b); map[i][j]=map[j][i]= b ? 0 : dis; } memset(used,0,sizeof(used)); printf("%d\n",Prim(n)); } return 0; }
Kruskal:(577MS)
因为要按权值排序,所以不能最后出得数的时候再决定是否置零
#include <cstdio> #include <algorithm> using namespace std; struct node { int b,e,dis; }s[5001]; int father[101]; bool cmp(node a,node b) { return a.dis<b.dis; } int find(int n) { return n==father[n] ? n : father[n]=find(father[n]); } int main() { int n; while(~scanf("%d",&n),n) { int m=n*(n-1)/2; for(int i=0;i<101;i++) father[i]=i; for(int i=0;i<m;i++) { bool flag; scanf("%d %d %d %d",&s[i].b,&s[i].e,&s[i].dis,&flag); if(flag) s[i].dis=0; } sort(s,s+m,cmp); int sum=0; for(int i=0;i<m;i++) { int x=find(s[i].b); int y=find(s[i].e); if(x!=y) { sum+=s[i].dis; //sum+= s[i].flag ? 0 : s[i].dis;
father[y]=x; } } printf("%d\n",sum); } return 0; }