2021 年东华大学金马程序设计联赛 C. Back--并查集判环

2021 年东华大学金马程序设计联赛 C. Back
搞了我好久,既然是错在多组输入,一样的代码不是多组输入就wa了,改多组就过了???
我不能接受!!!!!

题目描述:

There are N villages and M roads. If there is a road between two villages, they are directly reachable. If two villages are not directly reachable, they can first go to other directly reachable villages and then reach each other. We guarantee that there is at most one road between two villages, and each road is two-way, and any two villages can be reached. SDZ likes walking after dinner, but he doesn’t like to walk twice on the same road. He wondered whether there was a route, and he set off along this route, and eventually he could return to the starting point without the road being repeated.

输入格式

There are two numbers N and M in the first line, which means there are N villages and M roads. ( 1 ≤ N ≤ 1000 , 1 ≤ M ≤ N × ( N − 1 ) 2 ) (1≤N≤1000,1≤M≤N× \frac{(N−1)}{2}) (1N1000,1MN×2(N1))

In the next M line, each line has two numbers u, and v indicates that there is a road between village u and village v.

Note that there are multiple sets of inputs and the sum of N is not more than 5000 and the sum of M is not more than 1000000.

输出格式

If such a route can be found, output Yes, otherwise output No.

样例

input

1 1
1 1

output

Yes
#include<bits/stdc+**加粗样式**+.h>
using namespace std;
template <typename T> void debug(string s, T x) { cout << s << "=" << x << "\n"; }
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>pll;
const ll N = 1e5 + 5;
const ll MOD = 1e9 + 7;
const ll INF = 0x7fffffff;

int father[N];//father[i]的值是节点i的父节点的标号
int height[N];//用height[i]定义元素i的高度
void init_set() {
    for (int i = 1; i <= N; i++) {
        father[i] = i;//每个节点的父亲是他自己
        height[i] = 0;//初始化树的高度
    }
}
int find_set(int x) {//非递归版
    int r = x;
    while (father[r] != r) r = father[r]; //找到根结点
    int i = x, j;
    while (i != r) {
        j = father[i]; //用临时变量j记录
        father[i] = r; //把路径上元素的集改为根结点
        i = j;
    }
    return r;
//    if(x!=father[x])father[x]=find_set(father[x]);
//    return father[x];
}
void union_set(int x, int y) {//优化合并操作
    x = find_set(x);
    y = find_set(y);
    if (height[x] == height[y]) {
        height[x] = height[x] + 1;//合并,树的高度加1
        father[y] = x;
    }
    else {//把矮树并到高树上,高树的高度保持不变
        if (height[x] < height[y])  father[x] = y;
        else   father[y] = x;
    }
}

int main() {
    ios_base::sync_with_stdio(false), cin.tie(0);

    ll n, m;
    while (cin >> n >> m) {
        init_set();
        bool flag = false;
        for (ll i = 0; i < m; i++) {
            ll u, v;
            cin >> u >> v;
            ll t1 = find_set(u);//拿出u的父节点
            ll t2 = find_set(v);//拿出v的父节点
            if (t1 == t2)flag = true;//若u,v有相同的父节点则将u,v连接必成环
            union_set(u, v);//再将u,v合并
        }
        if (flag)cout << "Yes\n";
        else cout << "No\n";
    }
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值