Title Link:
https://www.luogu.org/problemnew/show/P2341
Title:
Given a directed graph, if aaa can reach bbb and bbb can reach ccc, then aaa can also reach ccc. Ask how many such points exist, so that all points can reach it through the directed edge, and output the number
Analysis:
First, we consider that any two points in a strongly connected component can reach each other. If all points outside the strongly connected component can reach any strongly connected internal point, then all points of the strongly connected component belong to the set of results. In this way, only all strongly connected components are required to be obtained, and then the strongly connected component with degree 0 is obtained after the point is reduced, and then the midpoint of the strongly connected component is output It should be noted that if there are multiple strongly connected components with 0 degree, it can be imagined that if there are two strongly connected components, it is obvious that the two strongly connected components do not arrive from either side, so the number of resultant points is 0, for example, there are isolated sets or points;
Code:
#include<iostream> #include<string> #include<queue> #include<set> #include<vector> #include<stack> #include<map> #include<cmath> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; const int inf=0x7f7f7f7f; const int maxn=5e4+50; const int N=1e4+50; typedef long long ll; typedef struct{ int u,v,next,lca; }Edge; Edge e[2*maxn]; typedef struct B{ int l,r; ll sum,lazy; void update(int value){ sum+=(r-l+1)*value; lazy+=value; } }Tree; Tree tree[4*maxn]; int cnt,head[maxn]; void add(int u,int v){ e[cnt].u=u; e[cnt].v=v; // e[cnt].w=w; // e[cnt].f=f; e[cnt].next=head[u]; head[u]=cnt++; // e[cnt].u=v; // e[cnt].v=u; // e[cnt].w=0; // e[cnt].f=-f; // e[cnt].next=head[v]; // head[v]=cnt++; } int read() { int x = 0; int f = 1; char c = getchar(); while (c<'0' || c>'9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0'&&c <= '9') { x = x * 10 + c - '0'; c = getchar(); } return x*f; } //_scc[u] stores the label of the strongly connected component of u point, and out[x] stores the output of the strongly connected component with the label of X, //The number of points in cot[x] memory labeled as X int sum,t,res,n,m,a,b,low[N],dfn[N],_time,vis[N],num,_scc[N],out[N],cot[N]; int stacK[N]; void tarjan(int u){ dfn[u]=low[u]=++_time; vis[u]=1; stacK[num++]=u; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].v; if(!dfn[v]){ tarjan(v); low[u]=min(low[v],low[u]); } else if(vis[v])low[u]=min(dfn[v],low[u]); } if(low[u]==dfn[u]){ res++; do{ t=stacK[--num]; vis[t]=0; _scc[t]=res; cot[res]++; }while(t!=u); } } int main() { cin>>n>>m; memset(head,-1,sizeof(head)); for(int i=0;i<m;i++){ cin>>a>>b; add(a,b); } for(int i=1;i<=n;i++){ if(!dfn[i])tarjan(i); } //cout<<res<<endl; for(int i=0;i<cnt;i++){ int u=e[i].u,v=e[i].v; if(_scc[u]!=_scc[v]){ out[_scc[u]]++; //cout<<_scc[u]<<" "<<u<<" "<<v<<endl; } } int outnum=0; for(int i=1;i<=res;i++){ if(out[i]==0){ outnum++; sum+=cot[i]; if(outnum>=2){ cout<<0<<endl; return 0; } } } cout<<sum<<endl; return 0; }
(for personal understanding only)