2762

来源:互联网 发布:伪娘 出柜 知乎 编辑:程序博客网 时间:2024/06/05 18:33

给定一个有向图,问任意两点u,v是否满足u能到v或v能到u。

tarjan缩点。然后进行拓扑排序,看结果是否唯一。(记录每个点的入度,每次只有一个入度为0的点)

主要还是想写一下tarjan。

#pragma GCC optimize("O2")#include<cstdio>#include<cstring>#include<iostream>#include<vector>#include<algorithm>#include<set>#include<map>using namespace std;#define rep(i,j,k) for(i=j;i<=k;++i)#define per(i,j,k) for(i=j;i>=k;--i)#define G getchar()#define LL long long#define pii pair<int,int>#define mkp make_pair#define X first#define Y secondconst int N=1005,NN=12005;int n,m;int he[N],ne[NN],to[NN],tot;int dfn[N],low[N],id,stk[N],Tp,inz[N],blg[N],blk;int the[N],tne[N],tto[NN],ttot;int q[N],in[N];void read(int &x){char ch=G;while(ch<48||ch>57)ch=G;for(x=0;ch>47&&ch<58;ch=G)x=x*10+ch-48;}void add(int x,int y){to[++tot]=y;ne[tot]=he[x];he[x]=tot;}void tarjan(int x){int i,y;dfn[x]=low[x]=++id;inz[stk[++Tp]=x]=1;for(i=he[x];i;i=ne[i]){if(!dfn[y=to[i]]){tarjan(y);low[x]=min(low[x],low[y]);}else if(inz[y])low[x]=min(low[x],dfn[y]);}if(dfn[x]==low[x]){++blk;do{inz[y=stk[Tp--]]=0;blg[y]=blk;}while(y!=x);}}void tadd(int x,int y){++in[tto[++ttot]=y];tne[ttot]=the[x];the[x]=ttot;}bool BFS(){int i,Ft=1,Rr=2,u,v;rep(i,1,blk)q[i]=0;rep(i,1,blk)if(!in[i]){if(q[1])return 0;q[1]=i;}while(Ft<Rr){for(i=the[u=q[Ft++]];i;i=tne[i]){if(!(--in[v=tto[i]])){if(q[Rr])return 0;q[Rr]=v;}}if(q[Rr])++Rr;}return 1;}int main(){int _,i,j,x,y;Tp=-1;for(read(_);_--;){read(n);read(m);rep(i,1,n)he[i]=0;tot=0;while(m--){read(x);read(y);add(x,y);}rep(i,1,n)dfn[i]=low[i]=0;id=blk=0;rep(i,1,n)if(!dfn[i])tarjan(i);ttot=0;rep(i,1,blk)the[i]=in[i]=0;rep(i,1,n){x=blg[i];for(j=he[i];j;j=ne[j])if(x!=(y=blg[to[j]]))tadd(x,y);}puts(BFS()?"Yes":"No");}return 0;}

原创粉丝点击