【最小生成树】Bzoj1601[Usaco2008 Oct]灌水

Description

Farmer John已经决定把水灌到他的n(1<=n<=300)块农田,农田被数字1到n标记。把一块土地进行灌水有两种方法,从其他农田饮水,或者这块土地建造水库。 建造一个水库需要花费wi(1<=wi<=100000),连接两块土地需要花费Pij(1<=pij<=100000,pij=pji,pii=0). 计算Farmer John所需的最少代价。

 

Sulotion

直接搞好像不太好做?于是新设一个点,作为总水源,和i点边权为wi,然后直接求最小生成树即可。

很快就想到了,不过好像并没有什么。真是灌水呐。

 

Code

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxn=305;
 5 
 6 int p[maxn];
 7 int find(int x){return p[x]==x?x:p[x]=find(p[x]);}
 8 struct edge{
 9     int u,v,w;
10     bool operator <(const edge&a)
11         const {return w<a.w;}
12 }e[maxn*maxn+maxn];
13 int n,k;
14 
15 int main(){
16     scanf("%d",&n);
17     for(int i=0;i<=n;i++) p[i]=i;
18     int w;
19     
20     for(int i=1;i<=n;i++){
21         scanf("%d",&w);
22         e[++k].u=0,e[k].v=i;
23         e[k].w=w;
24     }
25     for(int i=1;i<=n;i++)
26         for(int j=1;j<=n;j++){
27             scanf("%d",&w);
28             e[++k].u=i,e[k].v=j;
29             e[k].w=w;
30         }
31     sort(e+1,e+k+1);
32     
33     long long ans=0;
34     for(int i=1;i<=k;i++){
35         int x=find(e[i].u),y=find(e[i].v);
36         if(x!=y) p[x]=y,ans+=e[i].w;
37     }
38     
39     printf("%lld\n",ans);
40     return 0;
41 }

 

posted @ 2015-06-03 02:21  CyanNode  阅读(220)  评论(0编辑  收藏  举报