CLO [POI/BZOJ 1116]

33 篇文章 0 订阅
20 篇文章 0 订阅

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1116

[分析]

题目中要求“你要把其中一些road变成单向边使得:每个town都有且只有一个入度”。

那么,什么时候能满足这个条件呢?
我们思考一下:在一个连通分量中,当其中有环的时候,我们可以通过删边(不将它变为有向边)使这个环上的点都有且只有一个入度。因为它们构成了环,所以必然还有出边。在连通分量中,每一个点都可以间接或直接地被这些出边所连接,及它们一定会有入度,而我们也可以通过删边将它们变为有且只有一个入度的点。

综上,在一个连通分量中,只要有环,则其中的所有点都可以通过“把其中一些road变成单向边”变为有且只有一个入度的点。

所以算法就很显然了:逐个考虑连通分量,判断是否存在环。若每个连通分量中都存在环,则图就满足条件。至于如何判环,就看各位的爱好了。

#include <iostream>
#include <cstdio>

using namespace std;

int n,m;
int inp[200010][3];
int fa[200010];
int mem[100010];
bool is_circle[100010];

int find(int x){
	int tmp=x,pre;
	while(tmp!=fa[tmp])tmp=fa[tmp];
	while(x!=tmp){
		pre=fa[x];
		fa[x]=tmp;
		x=pre;
	}
	return tmp;
}

void merge(int x,int y){
	int fx=find(x),fy=find(y);
	fa[fx]=fy;
}

void merge2(int x,int y){
	int fx=find(x),fy=find(y);
	if(fx==fy)is_circle[mem[fx]]=true;
	else fa[fx]=fy;
}

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 x,y;
		scanf("%d%d",&x,&y);
		inp[i][1]=x;
		inp[i][2]=y;
		merge(x,y);
	}
	for(int i=1;i<=n;i++){int fi=find(i);mem[i]=fi;}
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=1;i<=m;i++)merge2(inp[i][1],inp[i][2]);
	for(int i=1;i<=n;i++)
		if(!is_circle[mem[i]]){printf("NIE");return 0;}
	printf("TAK"); 
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值