链接: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≤105
T图论,二分,拓扑排序
题意是想让大家判断有向图是否存在环。判断有向图是否有环可以使用拓扑排序。
但是不能每次加边的时候就进行判断。
由于不存在撤销操作,所以可以发现答案一定是一连串的Yes后再有一连串的No。
只需要二分最后一个Yes的位置,用拓扑排序/DFS判环即可。
原创傻逼二分(感觉应该对了,水一发过了)
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define mod 1000000007
#define MAXN 1000005
#define pai acos(-1)
int n,m;
struct node{
int a,b;
}arc[MAXN*2];
int in[MAXN*2];
vector<int>v[MAXN];
int topu(int r){
memset(in,0,sizeof(in));
queue<int> q;
for(int i=1;i<=MAXN-5;i++){
v[i].clear();
}
for(int i=1;i<=r;i++){
in[arc[i].b]++;
v[arc[i].a].push_back(arc[i].b);
}
for(int i=1;i<=MAXN-5;i++){
if(in[i]==0) q.push(i);
}
while(!q.empty()){
int x=q.front();
for(int i=0;i<v[x].size();i++){
in[v[x][i]]--;
if(in[v[x][i]]==0)
q.push(v[x][i]);
}
q.pop();
}
for(int i=1;i<=MAXN-5;i++){
if(in[i]!=0) return 1;
}
return 0;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&arc[i].a,&arc[i].b);
}
int ll=1,rr=m,t1,t2,ans;
while(ll<=rr){
int mid=(ll+rr)/2;
t1=topu(mid);
t2=topu(mid+1);
if(t1==0&&t2==1) {
ans=mid;
break;
}
else if(t2==0){
ll=mid+1;
}
else if(t1==1){
rr=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;
}