CodeForces - 25D Roads not only in Berland (并查集)

分析:利用并查集处理每一条边上两点的关系。假设两个点已直接或间接可互达,在此之外又连有额外的边,那么该条边应该被重建(集合合并问题)。

#include
using namespace std;
const int N = 1e3 + 5;
typedef pair P;
int fa[N], Rank[N];
int find(int x) {
    if(x == fa[x])
        return x;
    else
        return fa[x] = find(fa[x]);
}
bool Merge(int u, int v) {
    if(u > v)
        swap(u, v);
    int x = find(u);
    int y = find(v);
    if(x != y) {
        fa[y] = x;
        Rank[x] += Rank[y];
        return true;
    }
    return false;
}
struct data {
    int i, j, u, v;
    data(int i, int j, int u, int v): i(i), j(j), u(u), v(v) { }
};
int main() {
    int n, i, j;
    scanf("%d", &n);
    for(i = 1; i <= n; i += 1) {
        fa[i] = i;
        Rank[i] = 1;
    }
    int x, y;
    vector

v; for(i = 1; i < n; i += 1) { scanf("%d%d", &x, &y); if(!Merge(x, y)){ v.push_back(P(x, y)); //应该被重建的边 } } if(Rank[find(n)] == n) printf("0\n"); else { vector Set; for(i = 1; i <= n; i += 1) { if(find(i) == i){ //处理出目前所有的集合 Set.push_back(i); } } bool vis[N]; memset(vis, false, sizeof(vis)); vector res; for(i = 0; i < Set.size(); i += 1) { for(j = 0; j < v.size(); j += 1) { if(vis[j]){ continue; } if(Merge(v[j].first, Set[i])) { //集合合并 vis[j] = true; res.push_back(data(v[j].first, v[j].second, v[j].first, Set[i])); } } } printf("%d\n", (int)res.size()); for(i = 0; i < (int)res.size(); i += 1) printf("%d %d %d %d\n", res[i].i, res[i].j, res[i].u, res[i].v); } return 0; } /* 7 1 2 1 3 2 3 3 4 4 5 3 5 */

 

你可能感兴趣的:(图论)