P8346 最澄澈的空与海【无向图拓扑】

题意

给定 2n 个点、m 条边的二分图(可能有重边),左部点与右部点个数相同,判断其完美匹配数量是否恰好为 1。是则输出 Renko,否则输出 Merry

:完美匹配是指,从边集中选出 n 条边,这些边的顶点组成的点集恰好覆盖了所有的 2n 个点。

 解法

对于图论的题,尤其是这种题,要关注(入度)这个关键概念

(无向图没有入度出度之分,入度等于出度,统一为度,开一个数组记录即可)

纸上模拟可知:

对于一个度为1的u点,与他匹配的只能是对应的v点。一组确定的点,不能改变的匹配就这样确定了。用del数组记录已经确定的点的集合

再继续将v点所对应的边都删去,将度为1的点入队,重复上述过程。

统计cnt,如果==2n则唯一确定。

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 2 * 1e6 + 10;
int du[N];
vector<int> G[N];
bool del[N];
int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int t, cnt;
    cin >> t;
    while(t -- ) {
        cnt = 0;
        int n, m;
        cin >> n >> m;
        //memset(du, 0, sizeof du);
        //memset(del, 0, sizeof del);
        for (int i = 0; i < m; i ++ ) {
            int x, y;
            cin >> x >> y;
            G[x].push_back(y + n);
            G[y + n].push_back(x);
            du[x]++, du[y + n]++;
        }
        queue<int> q;
        for (int i = 1; i <= 2 * n; i ++ ) {
            if(du[i] == 1)q.push(i);
        }
        while(q.size()) {
            int u = q.front();
            q.pop();
            if(del[u] || du[u] != 1) continue;
            del[u] = 1;
            cnt ++;
            int id;
            for (int i = 0; i < (int)G[u].size(); i ++ ) {
                if(!del[G[u][i]]) id = G[u][i];
            }   
            cnt ++;
            del[id] = 1;
            for (int i = 0; i < (int)G[id].size(); i ++ ) {
                if(del[G[id][i]]) continue;
                if((-- du[G[id][i]])== 1) {
                    q.push(G[id][i]);
                }
            }
        }
        cout << (n*2 == cnt ? "Renko" : "Merry") << '\n';
        for (int i = 1; i <= 2 * n; i ++ )du[i] = del[i] = 0, G[i].clear();

    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值