题目大意:输入一个整数n,表示有n个村庄。在接下来的n(n-1)/2行中,每行有4个整数begin end weight flag。分别表示从begin到end之间可以连通
,他们之间的费用为weight,flag表示这条路是否已经修好。求修路让所有村庄都连起来的最小费用
解题思路:最小生成树
代码如下:
/* * 1879_4.cpp * * Created on: 2013年8月25日 * Author: Administrator */ #include <iostream> using namespace std; const int maxn = 110; int father[110000];//注意这里不要只开到father[110],否则会WA struct edge{ int begin; int end; int weight; }; edge e[maxn*maxn];//因为m的取值是n(n-1)/2,所以他应该是maxn*maxn的形式 int n; bool compare(const edge& a , const edge& b){ return a.weight < b.weight; } int find_set(int x){ if( x == father[x]){ return x; } father[x] = find_set(father[x]); return father[x]; } void kruskal(){ int i; int sum = 0; //初始化 for(i = 1 ; i <= n ;++i){ father[i] = i; } //合并 for(i = 1 ; i <= n ; ++i){ int fx = find_set(e[i].begin); int fy = find_set(e[i].end); if(fx != fy){ father[fx] = fy; sum += e[i].weight; } } printf("%d ",sum); } void init(){ int i,t; for( i = 1 ; i <= n ; ++i){ scanf("%d%d%d%d",&e[i].begin,&e[i].end,&e[i].weight,&t); if(t){ e[i].weight = 0; } } } int main(){ while(scanf("%d",&n)!=EOF,n){ // 这种写法会WA // int m = n*(n - 1)/2; // // int i; // for( i = 1 ; i <= m ; ++i){ // int flag ; // scanf("%d%d%d%d",&e[i].begin,&e[i].end,&e[i].weight,&flag); // // if(flag){ // e[i].weight = 0; // } // } n = n*( n - 1)/2; init(); sort(e + 1,e + n + 1 , compare); kruskal(); } }