$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$ 并查集的主要内容,如果未能解决你的问题,请参考以下文章