1116: [POI2008]CLO 思路题 并查集

开始看错题了囧。。。
要求选一部分边变为单向边。。并不是全都要变QAQ。
这样就比较好考虑了:
如果原图没有环,我们改变边的方向只会构造出一个类似树形结构,总会有点没有入度。而如果原图有环,我们构造一个基环外向树就好啦。。。
于是并查集维护一下:
如果当前两个点在一个联通块内,那么就在根上打一个标记。否则合并的时候如果有一个联通块有标记(证明有环)则合并后的也有标记。。最后check一下是否每个联通块的根都有标记就好啦。

#include<bits/stdc++.h>
using namespace std;
int n,m,f[100005];
bool v[100005];
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
int find(int i)
{
    return f[i]==i?i:f[i]=find(f[i]);
}
int main()
{
    n=read(); m=read();
    for (int i=1;i<=n;i++) f[i]=i;
    for (int i=1;i<=m;i++)
    {
        int x=read(),y=read(),p=find(x),q=find(y);
        if (p!=q)
        {
            f[p]=q;
            v[q]|=v[p];
        }
        else v[p]=1;
    }
    for (int i=1;i<=n;i++)
        if (!v[find(i)]) 
        {
            puts("NIE");
            return 0;
        }
    puts("TAK");
    return 0;
}   

你可能感兴趣的:(1116: [POI2008]CLO 思路题 并查集)