$bzoj1116-POI2008$ $CLO$ 并查集

Posted shjrd-dlb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了$bzoj1116-POI2008$ $CLO$ 并查集相关的知识,希望对你有一定的参考价值。

  • 题面描述
    • \(Byteotia\)城市有\(n\)\(towns\)\(m\)条双向\(roads\). 每条 \(road\) 连接 两个不同的 \(towns\) ,没有重复的\(road\).
    • 你要把其中一些\(road\)变成单向边使得:每个\(town\)都有且只有一个入度
  • 输入格式
    • 第一行输入\(n,m\). \((1 \leq n\leq 10^5,1\leq m \leq 2*10^5)\)
    • 下面\(M\)行用于描述\(M\)条边.
  • 输出格式
    • \(TAK/NIE\)
  • 题解
    • 考虑每个点都有一个入度,因此 被定向的边数\(=\)点数,因此不难想到被定向后的边组成的图形是一个基环外向树,因此在原图每个联通块中,必然要存在一个环,不然就不能达成目的
    • 因此用并查集判断是否有环即可
      • 具体来说,一条一条边加入,当将要被加入的点已经在要加入的集合中时即存在环
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=1e5+5;
const int MAXM=1e6+6;
int n,m,fa[MAXN];
int mark[MAXN];
int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]); }
void uion(int x,int y){ 
    int fx=find(x),fy=find(y);
    fa[fx]=fy;
    mark[fy]|=mark[fx];
}
int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) fa[i]=i;
    for (int i=1;i<=m;i++){
        int u,v; scanf("%d%d",&u,&v);
        int fu=find(u),fv=find(v);
        if (fu!=fv) uion(u,v);
        else mark[fu]=1;
    }
    for (int i=1;i<=n;i++){
        int fi=find(i);
        if (!mark[fi]) return printf("NIE\n"),0;
    }
    printf("TAK\n");
    return 0;
}

以上是关于$bzoj1116-POI2008$ $CLO$ 并查集的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1116 [POI2008]CLO

bzoj1116 [POI2008]CLO

bzoj1116 [POI2008]CLO

BZOJ 1116 [POI2008]CLO(并查集)

$bzoj1116-POI2008$ $CLO$ 并查集

BZOJ 1116: [POI2008]CLO [连通分量]