藍橋杯 歷屆試題 城市建設 最小生成樹
阿新 • • 發佈:2019-02-20
把碼頭作為0點處理。
首先判斷不建碼頭是否可以生成最小生成樹
最小生成樹用kruskal演算法,若對於代價<0的邊,直接加入
若可以:Min(最小生成樹(不建碼頭),最小生成樹(建碼頭));
若不可:最小生成樹(建碼頭)
#include "stdio.h" #include "string.h" #include "algorithm" using namespace std; int father[10010]; struct Link { int a,b,v; }link[110001]; int Min(int a,int b) { if (a<b) return a; else return b; } int fin(int x) { if (x==father[x]) return x; father[x]=fin(father[x]); return father[x]; } bool cmp(Link a,Link b) { return a.v<b.v; } int kruskal(int m) { int sum,i,fa,fb; sum=0; for (i=0;i<m;i++) { fa=fin(link[i].a); fb=fin(link[i].b); if (fa!=fb || link[i].v<0) { sum+=link[i].v; father[fa]=fb; } } return sum; } int main() { int n,m,i,cnt,fa,fb,ans,x; scanf("%d%d",&n,&m); for (i=0;i<=n;i++) father[i]=i; for (i=0;i<m;i++) scanf("%d%d%d",&link[i].a,&link[i].b,&link[i].v); cnt=0; for (i=1;i<=n;i++) { scanf("%d",&x); if (x!=-1) { link[m+cnt].a=0; link[m+cnt].b=i; link[m+cnt].v=x; cnt++; } } for (i=0;i<m;i++) { fa=fin(link[i].a); fb=fin(link[i].b); father[fa]=fb; } for (i=2;i<=n;i++) if (fin(1)!=fin(i)) break; if (i==n+1) { for (i=0;i<=n;i++) father[i]=i; sort(link,link+m,cmp); ans=kruskal(m); for (i=0;i<=n;i++) father[i]=i; sort(link,link+m+cnt,cmp); ans=Min(ans,kruskal(m+cnt)); printf("%d\n",ans); } else { for (i=0;i<=n;i++) father[i]=i; sort(link,link+m+cnt,cmp); printf("%d\n",kruskal(m+cnt)); } return 0; }