K. Birdwatching 题解(bfs)
原题链接https://codeforces.ml/gym/294361/problem/K
题意
有一个原图G和给你一个图P,都是有向图,G是P的子集
G与P的关系是:G图中可能没有a到b这条边,但是有路径可以到从a到b,那么P图可能就会多一条a到b的边。
现在给你P图和节点T,试问边(a->T)中哪些a是一定存在于原图G的
解法
可以想象的是对于所有a,如果有两条路径不重复路径能到T那就是不一定存在于原图。
为了方便可以把图反着建立,从T点开始bfs,找所有相邻点是否有两条以上路径到达,注意要排除a是一个环中唯一与T相邻的点的情况(这种时候也是一定存在于原图的)。
写法很多种,主要按方法走就行了
CODE:
1 /* 2 https://codeforces.ml/gym/294361/problem/K 3 bfs graph 4 */ 5 #include<bits/stdc++.h> 6 #define to_l(a) ((a)<<1) 7 #define to_r(a) ((a)<<1|1) 8 #define lowbit(a) ((a)&(-a)) 9 using namespace std; 10 typedef long long int ll; 11 typedef unsigned long long int ull; 12 const int int_inf=0x3f3f3f3f; 13 const ll ll_inf=0x3f3f3f3f3f3f3f3f; 14 const int max_n=1e5+5; 15 int head[max_n],to[max_n],nxt[max_n],ind; 16 inline void add(int a,int b){ 17 to[++ind]=b; 18 nxt[ind]=head[a]; 19 head[a]=ind; 20 return ; 21 } 22 int vis[max_n],from[max_n]; 23 void bfs(int s) 24 { 25 queue<int> q; 26 queue<int> qq; 27 while(!q.empty()) q.pop(); 28 while(!qq.empty()) qq.pop(); 29 for(int i=head[s];i;i=nxt[i]){ 30 q.push(to[i]); 31 qq.push(to[i]); 32 from[to[i]]=to[i]; 33 vis[to[i]]=1; 34 } 35 vis[s]=2; 36 while(!q.empty()){ 37 int t=q.front(),tt=qq.front(); 38 q.pop(),qq.pop(); 39 for(int i=head[t];i;i=nxt[i]){ 40 if(vis[to[i]]!=2){ 41 if(vis[to[i]]){ 42 if(tt!=from[to[i]]){ 43 vis[to[i]]++; 44 q.push(to[i]); 45 qq.push(tt); 46 } 47 }else{ 48 vis[to[i]]++; 49 from[to[i]]=tt; 50 q.push(to[i]); 51 qq.push(tt); 52 } 53 } 54 } 55 } 56 return ; 57 } 58 int main() 59 { 60 ios::sync_with_stdio(false); 61 cin.tie(0); 62 int i,j; 63 int n,m,t; 64 cin>>n>>m>>t; 65 ind=0; 66 for(i=0;i<n;i++) from[i]=-1; 67 for(i=0;i<m;i++){ 68 int a,b; 69 cin>>a>>b; 70 add(b,a); 71 } 72 bfs(t); 73 vector<int>ans; 74 ans.clear(); 75 for(i=head[t];i;i=nxt[i]){ 76 if(vis[to[i]]!=2){ 77 vis[to[i]]=3; 78 } 79 } 80 for(i=0;i<n;i++){ 81 if(vis[i]==3){ 82 ans.push_back(i); 83 } 84 } 85 cout<<ans.size()<<endl; 86 for(i=0;i<ans.size();i++){ 87 cout<<ans[i]<<endl; 88 } 89 return 0; 90 }

浙公网安备 33010602011771号