bzoj 1116: [POI2008]CLO

Description

Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 你要把其中一些road变成单向边使得:每个town都有且只有一个入度

Input

第一行输入n m.1 <= n<= 100000,1 <= m <= 200000 下面M行用于描述M条边.

Output

TAK或者NIE 常做POI的同学,应该知道这两个单词的了...

Sample Input

4 5
1 2
2 3
1 3
3 4
1 4

Sample Output

TAK

上图给出了一种连接方式.

 

思路:

考虑每个连通块。如果一个连通块有 n 条边,那么一定满足条件。

所以我们用并查集来维护n-1条边。如果 x y 同时出现在一个联通块中,

那么这个连通块一定合法。有n 条边,把这个连通块的根节点标记一下。 

然后合并两个连通块。 如果两个连通块里存在一个连通块合法。那这个新的连通块一定合法。

存在一个连通块合法,那么就是有n-1条边,加上新的一条边。那就是n 条边。所以新的连通块合法。然后标记。

最后扫描一遍,如果有一个连通块没有被标记就直接输出  NIE。

否则输出  TAK

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n,m;
int f[N];
bool vis[N];

int find(int k){
	if (f[k] == k) return k; else return 
	f[k] = find(f[k]);
}
int main(){
	int x,y;
	scanf("%d%d",&n,&m);
	for (int i = 0; i <= n; ++i) f[i] = i;
	for (int i = 0; i < m; i++){
		scanf("%d%d",&x,&y);
		int xx = find(x), yy = find(y);
		if (xx != yy){
			f[xx] = yy;
			vis[yy] = (vis[xx] | vis[yy]);
		} else vis[xx] = 1;
	}

	for (int i = 1; i <= n; ++i)
		if (find(i) == i) if (!vis[i]){
			puts("NIE"); 
			return 0;
		}

	puts("TAK");
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值