题目没读懂...看了别人的结题报告才知道是要判断是否为弱连通图
u与v之间,只要u->v和v->u之间至少存在一条边就可以了
对于有向图,强连通分量中的点必然满足,所以先缩点,再拓扑排序求最长链,最长链的顶点数如果等于缩点后的顶点数,则为弱连通图
简单证明:首先,如果最长链上的顶点数等于DAG图的顶点数,则所有顶点在一棵树上,从根节点可以到达任意节点,任意顶点对直接至少存在一条边
如果最长链上的顶点数小于DAG图的顶点数,假设i不在最长链上,则最长链上存在点对x,y,x和y之间不存在边相连:
1.如果最长链与i所在的链不相交,显然的
2.如果最长链与i所在的链相交,有几种情况,自己画画就知道,认为点i之前的点为i的前驱点,点i之后的点为i的后继点,设j为相交的点,则两条链中,必然存在一种情形:j的某些前驱节点和后继节点相互不可达
如果本身就不是弱连通图的话,必定存在i,j,之间没有边,那么最长链的顶点数肯定小于缩点后的顶点数
代码:
#include<iostream> #include<stack> using namespace std; const int MAX=1005; struct node { int v,next; }g1[MAX*MAX],g2[MAX*MAX]; int adj1[MAX],adj2[MAX],dfn[MAX],low[MAX],inStack[MAX],bel[MAX],ind[MAX],num[MAX]; bool map[MAX][MAX]; int e1,e2,index,cnt,n,m; stack<int>s; void add1(int u,int v) { g1[e1].v=v; g1[e1].next=adj1[u]; adj1[u]=e1++; } void add2(int u,int v) { g2[e2].v=v; g2[e2].next=adj2[u]; adj2[u]=e2++; } void tarjan(int u) { dfn[u]=low[u]=++index; s.push(u); inStack[u]=1; int i,v; for(i=adj1[u];i!=-1;i=g1[i].next) { v=g1[i].v; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(inStack[v]) { low[u]=min(low[u],dfn[v]); } } if(low[u]==dfn[u]) { cnt++; do { v=s.top(); s.pop(); inStack[v]=0; bel[v]=cnt; }while(u!=v); } } void topsort() { memset(num,0,sizeof(num)); int i,u,v; while(!s.empty()) s.pop(); for(i=1;i<=cnt;i++) if(ind[i]==0) { s.push(i); num[i]++; } while(!s.empty()) { u=s.top(); s.pop(); for(i=adj2[u];i!=-1;i=g2[i].next) { v=g2[i].v; if(--ind[v]==0) { s.push(v); num[v]=num[u]+1; } } } } int main() { int i,j,T; scanf("%d",&T); while(T--) { e1=e2=index=cnt=0; memset(dfn,0,sizeof(dfn)); memset(adj1,-1,sizeof(adj1)); memset(adj2,-1,sizeof(adj2)); memset(map,false,sizeof(map)); scanf("%d%d",&n,&m); while(m--) { scanf("%d%d",&i,&j); add1(i,j); //add1(j,i); } for(i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int u=1;u<=n;u++) { for(i=adj1[u];i!=-1;i=g1[i].next) { int v=g1[i].v; if(bel[u]!=bel[v]&&(!map[bel[u]][bel[v]])) { map[bel[u]][bel[v]]=true; add2(bel[u],bel[v]); ind[bel[v]]++; } } } topsort(); int ans=-1; //cout<<cnt<<endl; for(i=1;i<=cnt;i++) { ans=max(ans,num[i]); //cout<<num[i]<<endl; } if(ans==cnt) puts("Yes"); else puts("No"); } return 0; }