题解 | 继续畅通工程
继续畅通工程
https://www.nowcoder.com/practice/16212f7d46e44174b5505997ea998538
#include <iostream> #include <algorithm> using namespace std; int village[101]; typedef struct Edge{ int a, b; int cost; int status; } Edge; Edge edge[5000]; bool cmp(Edge a, Edge b){ if(a.status != b.status) return a.status > b.status; // 已修的边,先于未修的边 return a.cost < b.cost; // 成本低的先于成本搞得 } // 判断是否联通 bool isSameSet(){ int res=0; for(int i=1; i<=village[0]; i++){ if(village[i] == -1) res++; if(res > 1) return false; } return true; } // 寻找当前节点的根节点 int findRoot(int a){ if(village[a] == -1) return a; // 判断是否为根节点 int tmp = findRoot(village[a]); // 递归查找父节点的根节点 village[a] = tmp; // 将当前节点的父节点直接设置为根节点,因为集合查找是否同属于一个集合的时候,是看根节点是否相同 return tmp; } int main() { int n; while(cin>>n){ if(n==0) break; // 初始化,每个节点单独一个集合 for(int i=1; i<=n; i++){ village[i] = -1; } village[0] = n; // 村落的个数 int lines = n*(n-1)/2; for(int i=0; i<lines; i++){ cin >> edge[i].a >> edge[i].b >> edge[i].cost >> edge[i].status; } // 排序 sort(edge, edge+lines, cmp); // 计算 int sum=0; int cur=0; // 判断是否联通,判断是否修完所有的路 while(!isSameSet() && cur < lines){ int a_root = findRoot(edge[cur].a); int b_root = findRoot(edge[cur].b); // 如果两者根节点不相同,证明不在同一集合,不连通 if(a_root != b_root){ village[a_root] = b_root; // 如果还没修路,则增加花费 if(edge[cur].status == 0) sum+=edge[cur].cost; } cur++; } cout << sum << endl; } }