Applese 的QQ群--(判断图是否成环)

链接:https://ac.nowcoder.com/acm/contest/330/F
来源:牛客网
 

Applese 的QQ群

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

Applese 有一个QQ群。在这个群中,大家互相请教问题。如 b 向 a 请教过问题,就把 a 叫做是 b 的"老板"。这样一个群中就会有很多老板。


同时规定:如果 a 是 b 的老板,b 是 c 的老板,那么 a 也是 c 的老板。

为了不破坏群里面和谐交流的氛围,Applese 定了一个群规:不允许出现 a 既是 b 的老板, b 又是 a 的老板。

你需要帮助 Applese 判断大家是否遵守了群规。

输入描述:

第一行两个整数 n, m,表示群里的人数以及请教问题的数量。
接下来 m 行,每行两个整数 a, b,表示 a 是 b 的"老板",即 b 向 a 请教了一个问题。
注:无论是否违反了群规,a 都会成为 b 的老板。

输出描述:

对于每次提问,输出一行"Yes"表示大家都遵守了群规,反之输出"No"。

示例1

输入

复制

4 4
1 2
2 3
3 1
1 4

输出

复制

Yes
Yes
No
No

备注:

1≤n≤1051≤n≤105
1≤m≤2⋅1051≤m≤2⋅105
1≤a,b≤n

判断图是否成环有两种做法,一个是二分+拓扑排序和dfs判断的方法。

二分+拓扑排序:


#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=100005;
int n,m;
int in[N];
struct node{
	int s,e;
}edge[N<<1];

int check(int mid){
	memset(in,0,sizeof(in));
	vector<int>v[N];
	for(int i=1;i<=mid;i++){
		v[edge[i].s].push_back(edge[i].e);//建图
		in[edge[i].e]++; 
	} 
	int sum=0;
	queue<int>q;
	for(int i=1;i<=n;i++)
	if(!in[i]) q.push(i);	 
	while(q.size()){
		int x=q.front();q.pop();
		sum++;
		for(int i=0;i<v[x].size();i++){
			in[v[x][i]]--;
			if(in[v[x][i]]==0) q.push(v[x][i]); 
		}
	} 
	return sum==n;//出来的点的总数为n说明不存在环
} 

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
		scanf("%d%d",&edge[i].s,&edge[i].e);
		
	int l=1,r=m,ans;
	while(l<=r){
		int mid=l+(r-l)/2;
		if(check(mid)){//此时中点前面不存在环,存在环的点在右边 
			l=mid+1;
			ans=mid;//记录不存在环的最后一个点 
		}else{
			r=mid-1;
		} 
	}
	for(int i=1;i<=ans;i++) printf("Yes\n"); 
	for(int i=ans+1;i<=m;i++) printf("No\n");
	return 0;
} 

dfs方法:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=100005;
vector<int>v[N];
int dfs(int a,int b){
	for(int i=0;i<v[a].size();i++){
		if(v[a][i]==b) return 1;//a的老板是b
		if(dfs(v[a][i],b)) return 1;//dfs a的老板的老板是b 返回1 
	} 
	return 0;
}
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	int flag=0;
	while(m--){
		int a,b;
		scanf("%d%d",&a,&b);//a是b的老板 
		if(flag||dfs(a,b)){//dfs a的老板是不是b 
			flag=1;
			printf("No\n");
		}else{
			v[b].push_back(a);
			 printf("Yes\n"); 
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/88523863