【最小生成树】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 }