7-50 暢通工程之區域性最小花費問題(35 分)
阿新 • • 發佈:2019-01-22
題目大意:略。
解題思路:Kruskal 演算法+首先要將已經修建的道路進行並查集合併操作,用 set 存集合中結點的個數來判斷是否所有點都已經操作完成,剩餘的點按照基本操作進行就好了。
AC 程式碼
#include<bits/stdc++.h> #include<cmath> #define mem(a,b) memset(a,b,sizeof a); #define INF 0x3f3f3f3f using namespace std; typedef long long ll; const int maxn=110; struct edge { int u,v,w,f; }es[maxn*maxn]; int n,m; int pre[maxn]; set<int> st; // 判斷是否所有點都已經操作完成 void init() { st.clear(); m=n*(n-1)/2; for(int i=1;i<=n;i++) pre[i]=i; } int cmp(edge e1,edge e2) { if(e1.f==e2.f) return e1.w<e2.w; return e1.f>e2.f; } int find(int x) { return pre[x]==x ? x : pre[x]=find(pre[x]); } int kruskal() { int ans=0,fu,fv; for(int i=0;i<m;i++) { fu=find(es[i].u), fv=find(es[i].v); st.insert(es[i].u); st.insert(es[i].v); if(es[i].f==1) { pre[fu]=fv; } else if(fu!=fv) { ans+=es[i].w; pre[fu]=fv; } if(st.size()==n) break; } printf("%d\n",ans); } int main() { while(~scanf("%d",&n)) { init(); for(int i=0;i<m;i++) scanf("%d%d%d%d",&es[i].u,&es[i].v,&es[i].w,&es[i].f); sort(es,es+m,cmp); // 因為 Kruskal 演算法是按照邊從小到大選擇 kruskal(); } return 0; }