题目大意:给你一个由n个点和n-1条边组成的无向图,问你最多去掉几条边同时增加几条边可以使得原图成为一个连通图
解题思路:涉及到连通性问题,则考虑dfs或者并查集。本人采用了后者,读取每条边的同时,看两个端点是否处于一个联通块,若没有,则直接加入,否则将这条边加入一个元素为待删除的边的集合。读取完之后再把所有的点所属于的联通块(记录为根节点)放入一个set,最后轮流取出set中相邻的两项,将这两个点相连并且依次删除待删除集合中的边即可。
AC代码:
#include <iostream> #include <algorithm> #include <vector> #include <set> #include <utility> using namespace std; const int maxn = 1000; vector<pair<int,int> >clo; set<int> blo; struct DisjointSet { vector<int> father,rank; DisjointSet(int n):father(n+1),rank(n+1) { for (int i = 1;i<=n;i++) father[i] = i; } int find(int v) { return father[v] = father[v] == v ? v :find(father[v]); } void merge(int x,int y) { int a = find(x),b = find(y); if(rank[a]<rank[b]) father[a] = b; else { father[b] = a; if(rank[b] == rank[a]) ++rank[a]; } } }; int main() { int n,res = 0; cin >> n; DisjointSet che(n); for(int i = 0;i<n-1;i++) { int a,b; cin >> a >> b; if(che.find(b) == che.find(a)) clo.push_back(make_pair(a,b)); else che.merge(a,b); } for(int i = 1;i<=n;i++) blo.insert(che.find(i)); cout << blo.size()-1 << endl; int i = 0; for(set<int>::iterator it = blo.begin();it!=blo.end();it++) { if(i == clo.size())break; cout << clo[i].first << " " << clo[i].second << " "; cout << *it << " "; it++; cout << *it << endl; it--; i++; } return 0; }