[USACO08OCT]:打井Watering Hole(MST)
题意:有N个牧场,每个牧场修水井花费Wi,连接牧场花费Pij,问最小花费,使得每个牧场要么有水井,要么和有水井的牧场有通道。
思路:加一个格外的节点O,连接O表示修井,边权是修井的费用。 那么这N+1个点求最MST即可。
刘同学想到的解法: 先找到修井费用最低的的牧场,然后和上面一样,由于最低的那个必选,所以异曲同工。
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=310; const int maxm=maxn*maxn; int fa[maxn],t[maxn],a[maxn][maxn],tot; struct in{ int len,u,v; }s[maxm]; bool cmp(in w,in q) { return w.len<q.len; } void add(int u,int v,int len){ tot++; s[tot].u=u; s[tot].v=v; s[tot].len=len; } int find(int x){ if(x!=fa[x]) return fa[x]=find(fa[x]); return x; } int main() { int N,M,ans=0; scanf("%d",&N); rep(i,1,N) scanf("%d",&t[i]); rep(i,1,N) rep(j,1,N) { scanf("%d",&a[i][j]); if(a[i][j]) add(i,j,a[i][j]); } rep(i,0,N) fa[i]=i; rep(i,1,N) add(0,i,t[i]); sort(s+1,s+tot+1,cmp); rep(i,1,tot) { int fu=find(s[i].u); int fv=find(s[i].v); if(fu==fv) continue; fa[fu]=fv; ans+=s[i].len; } printf("%d\n",ans); return 0; }
It is your time to fight!