Book Club (tarjan算法)

Book Club

Porto’s book club is buzzing with excitement for the annual book exchange event!
Every year, members bring their favorite
book and try to find another book they like
that is owned by someone willing to trade
with them.
I have been to this book exchange before,
and I definitely do not want to miss it this
year, but I feel that the trading should be
improved. In the past, pairs of members
interested in each other’s books would simply trade: imagine that person A brought
a book that person B liked and vice-versa,
then A and B would exchange their books.
I then realized that many members were left with the same book they walked-in with… If
instead of looking for pairs I looked for triplets, I could find more valid exchanges! Imagine
that member A only likes member B’s book, while B only likes C’s book and C likes A’s
book. These 3 people could trade their books in a cycle and everyone would be happy!
But why stop at triplets? Cycles could be bigger and bigger! Could you help me find if it
is possible for everyone to go out with a new book? Be careful, because members will not
give their book without receiving one they like in return.
Task
Given the members of the book club and the books they like, can we find cycles so that
everyone receives a new book?
Input
The first line has two integers: N, the number of people, and M, the total number of
“declarations of interest”. Each of the following M lines has two integers, A and B, indicating that member A likes the book that member B brought (0 ≤ A, B < N). Numbers
A and B will never be the same (a member never likes the book he brought).
Output
You should output YES if we can find a new book for every club member and NO if that is
not possible.

Constraints
2 ≤ N ≤ 10 000
1 ≤ M ≤ 20 000 and M ≤ N2 − N.
Sample Input
9 9
0 1
1 2
2 0
3 4
4 3
5 6
6 7
7 8
8 5
Sample Output
YES

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int dfn[N], low[N], vis[N];
int k = 0, d[N], t = 0;
int q[N], top = 0, n, m;
int h[N], cnt = 0;
int r[N], l[N];
struct node {
    int y, ne;
} s[N];
void add(int x, int y) {
    s[++cnt].y = y;
    s[cnt].ne = h[x];
    h[x] = cnt;
}

void dfs(int x) {
    dfn[x] = low[x] = ++t;
    q[++top] = x;
    vis[x] = 1;
    for (int i = h[x]; i; i = s[i].ne) {
        int y = s[i].y;
        if (dfn[y] == 0) {
            dfs(y);
            low[x] = min(low[y], low[x]);
        } else if (vis[y]) {
            low[x] = min(low[x], dfn[y]);
        }
    }
    if (low[x] == dfn[x]) {
        int y;
        k++;
        do {
            y = q[top--];
            vis[y] = 0;
            d[k]++;

        } while (y != x);
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin >> n >> m;
    while (m--) {
        int x, y;
        cin >> x >> y;
        add(x, y);
        l[x]++;
    }
    int flag = 1;
    for (int i = 0; i < n; i++) {
        if (l[i] == 1) {
            int j = h[i];
            int y = s[j].y;
            r[y]++;
            if (r[y] > 1) {
                flag = 0;
                break;
            }
        }
    }
    if (flag) {
        for (int i = 0; i < n; i++) {
            if (dfn[i] == 0) dfs(i);
        }

        for (int i = 1; i <= k; i++) {
            if (d[i] == 1) {
                flag = 0;
                break;
            }
        }
    }
    if (flag)
        cout << "YES\n";
    else
        cout << "NO\n";
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值