HDU - 1879 继续畅通工程(最小生成树)
d.n个村庄,n*(n-1)/2条路,建立一些路使所有村庄可达。求建立路这些路的最小花费。
s.最小生成树
c.Prim算法:cost[a][b]和cost[b][a]都得赋值。
/* Prim算法 Prim求MST 耗费矩阵cost[][],标号从0开始,0~n-1 返回最小生成树的权值,返回-1表示原图不连通 */ #include<iostream> #include<stdio.h> #include<string.h> using namespace std; const int INF=0x3f3f3f3f; const int MAXN=110; bool vis[MAXN]; int lowc[MAXN]; //点是 0 n-1 int Prim(int cost[][MAXN],int n){ int ans=0; memset(vis,false,sizeof(vis)); vis[0]=true; for(int i=1;i<n;i++)lowc[i]=cost[0][i]; for(int i=1;i<n;i++){ int minc=INF; int p=-1; for(int j=0;j<n;j++) if(!vis[j]&&minc>lowc[j]){ minc=lowc[j]; p=j; } if(minc==INF)return -1;//原图不连通 ans+=minc; vis[p]=true; for(int j=0;j<n;j++) if(!vis[j]&&lowc[j]>cost[p][j]) lowc[j]=cost[p][j]; } return ans; } int main(){ int cost[MAXN][MAXN]; int N; int u,v,w,b; while(~scanf("%d",&N)){ if(N==0)break; for(int i=0;i<N;++i){ for(int j=0;j<N;++j){ cost[i][j]=INF; } } int M=N*(N-1)/2; for(int i=0;i<M;++i){ scanf("%d%d%d%d",&u,&v,&w,&b); --u;--v; if(b==0)cost[u][v]=cost[v][u]=w; else cost[u][v]=cost[v][u]=0; } printf("%d\n",Prim(cost,N)); } return 0; }