冗余连接

时间:2024-10-01 07:51:40

题目描述

有一个图,它是一棵树,他是拥有 n 个节点(节点编号1到n)和 n - 1 条边的连通无环无向图(其实就是一个线形图),如图:

现在在这棵树上的基础上,添加一条边(依然是n个节点,但有n条边),使这个图变成了有环图,如图:

先请你找出冗余边,删除后,使该图可以重新变成一棵树。

输入描述

第一行包含一个整数 N,表示图的节点个数和边的个数。

后续 N 行,每行包含两个整数 s 和 t,表示图中 s 和 t 之间有一条边。

输出描述

输出一条可以删除的边。如果有多个答案,请删除标准输入中最后出现的那条边。

输入示例

3
1 2
2 3
1 3

输出示例

1 3

提示信息

图中的 1 2,2 3,1 3 等三条边在删除后都能使原图变为一棵合法的树。但是 1 3 由于是标准输出里最后出现的那条边,所以输出结果为 1 3

数据范围:

1 <= N <= 1000.

思路:这道题比较简单,因为是无向图,所以在并查集的基础上使用isSame函数进行判断即可。

#include<iostream>
#include<vector>
using namespace std;

int n;
vector<int> parent(1001, 0);

//初始化并查集的各结点的根
void init(){
    for(int i = 0; i < n; i ++){
        parent[i] = i;
    }
}

//找结点的根
int find(int u){
    return u == parent[u] ? u : parent[u] = find(parent[u]);//路径压缩
}

//比较两结点的根是否相同
bool isSame(int u, int v){
    u = find(u);
    v = find(v);
    return u == v;
}

//将两结点加入并查集
//存在v->u这样一条边
void join(int u, int v){
    u = find(u);
    v = find(v);
    if(u == v) return;
    parent[v] = u;
}

int main(){
    while(cin >> n){
        init();
        int node1, node2;
        for(int i = 0; i < n; i ++){
            cin >> node1 >> node2;
            if(isSame(node1, node2)){
                cout << node1 << " " << node2 << endl;
                return 0;
            }
            join(node1, node2);
        }
    }
}