poj 2762 Going from u to v or from v to u?

<textarea cols="84" rows="21" name="code" class="cpp">// poj 2762 Going from u to v or from v to u? /* 题意: 判断一个有向图中是否任意两点都至少满足一点到另一点可达 题解: Robert Sedgewick著《C++算法--图算法》P179 PS: 由于作业比较多,做题时间有限,未做太多优化,望见谅 */ #include &lt;iostream&gt; #include &lt;cstdio&gt; #include &lt;cstring&gt; using namespace std; int n,m; int con[1010][1010],rcon[1010][1010]; //图和逆图 int id[1010],post[1010],pre[1010],cnt,scnt; //id标识强连分量,pre和post分别是前序后序编号 int r[1010][1010],tc[1010][1010]; //r是核心DAG,tc是其闭包 //图和逆图的两次遍历 void dfs(int con[][1010],int v,int flag){ id[v]=cnt; for (int i=0;i&lt;n;i++) if (con[v][i] &amp;&amp; id[i]==-1) { dfs(con,i,flag); } if (flag) post[scnt++]=v; } //求DAG的闭包 void tcR(int v){ pre[v] = scnt++; for (int i=0;i&lt;cnt;i++) if (r[v][i]){ tc[v][i]=1; if (pre[i]&gt;pre[v]) continue; if (pre[i]==-1) tcR(i); for (int j=0;j&lt;cnt;j++){ if (tc[i][j]){ tc[v][j]=1; } } } } int main() { int t,a,b; scanf("%d",&amp;t); while (t--){ memset(con,0,sizeof(con)); memset(rcon,0,sizeof(rcon)); memset(r,0,sizeof(r)); scanf("%d%d",&amp;n,&amp;m); while (m--){ scanf("%d%d",&amp;a,&amp;b); //printf("%d %d/n",a,b); con[a-1][b-1]=1; rcon[b-1][a-1]=1; } //算出原图顶点的后序编号 cnt=scnt=0; memset(id,-1,sizeof(id)); memset(post,-1,sizeof(post)); for (int i=0;i&lt;n;i++){ if (id[i]==-1){ dfs(con,i,1); cnt++; } } memset(id,-1,sizeof(id)); //按后序编号post的递减顺序再做一次DFS,进而求出核心DAG cnt=0; for (int i=n-1;i&gt;=0;i--){ if (id[post[i]]==-1){ dfs(rcon,post[i],0); cnt++; } } if (cnt==1){ printf("Yes/n"); continue; } scnt=0; //建立以强连通子图为顶点所形成的新图 for (int i=0;i&lt;n;i++) for (int j=0;j&lt;n;j++) if (con[i][j]) r[id[i]][id[j]]=1; //求新图的闭包 memset(pre,-1,sizeof(pre)); memset(tc,0,sizeof(tc)); tcR(0); bool flag = true; for (int i=0;i&lt;cnt &amp;&amp; flag;i++) for (int j=i+1;j&lt;cnt;j++) if (!tc[i][j] &amp;&amp; !tc[j][i]) { flag=false; break; } if (flag) printf("Yes/n"); else printf("No/n"); } system("pause"); return 0; } /* 5 4 1 2 2 3 2 4 4 5 */ </textarea>

你可能感兴趣的:(poj 2762 Going from u to v or from v to u?)