1. 程式人生 > >[模擬賽] T2 混合圖

[模擬賽] T2 混合圖

拓撲排序 整改 urn class 輸入 AI ron queue tdi

Description

Hzwer神犇最近又征服了一個國家,然後接下來卻也遇見了一個難題。 Hzwer的國家有n個點,m條邊,而作為國王,他十分喜歡遊覽自己的國家。他一般 會從任意一個點出發,隨便找邊走,沿途欣賞路上的美景。但是我們的 Hzwer 是一個奇怪 的人,他不喜歡走到自己以前走過的地方,他的國家本來有p1條有向邊,p2條無向邊,由 於國王奇怪的愛好,他覺得整改所有無向邊,使得他們變成有向邊,要求整改完以後保證他 的國家不可能出現從某個地點出發順著路走一圈又回來的情況。(註:m=p1+p2.) 概述:給你一張混合圖,要求你為無向圖定向,使得圖上沒有環。

Input

第一行3個整數 n,p1,p2,分別表示點數,有向邊的數量,無向邊的數量。 第二行起輸入p1行,每行2個整數 a,b 表示a到b有一條有向邊。 接下來輸入p2行,每行2個整數 a,b 表示a和b中間有一條無向邊。

Output

對於每條無向邊,我們要求按輸入順序輸出你定向的結果,也就是如果你輸出a b, 那表示你將a和b中間的無向邊定向為a->b。 註意,也許存在很多可行的解。你只要輸出其中任意一個就好。

Range

對於20%的數據 n<=10 p1<=10 p2<=5 對於30%的數據 n<=10 p1<=30 p2<=20 對於100%的數據 n<=100000 p1<=100000 p2<=100000 數據保證至少有一種可行解。

Solution

通過題目可以知道這道題其實是求一個DAG上的邊方向。我們先普及一下,一個圖是DAG的充要條件是有一個完整的拓撲序。這道題因為保證有解,所以我們可以先對輸入的有向邊拓撲排序一下,然後輸入無向邊的時候讓層次小的指向層次大的,這就構成了一個DAG。

Code

#include<queue>
#include<cstdio>
#include<cctype>
using namespace std;

queue<int> q;
int ru[100005];
int head[100005];
int ceng[100005];
int n,p1,p2,cnt,sum;

struct Edge{
    int to,nxt;
}edge[400005];

void add(int x,int y){
    edge[++cnt].to=y;
    edge[cnt].nxt=head[x];
    head[x]
=cnt; } void topsort(){ while(q.size()){ int u=q.front();q.pop(); ceng[u]=++sum; for(int i=head[u];i;i=edge[i].nxt){ ru[edge[i].to]--; if(!ru[edge[i].to]) q.push(edge[i].to); } } } signed main(){ scanf("%d%d%d",&n,&p1,&p2); for(int i=1;i<=p1;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y); ru[y]++; } for(int i=1;i<=n;i++){ if(!ru[i]) q.push(i); } topsort(); for(int i=1;i<=p2;i++){ int x,y; scanf("%d%d",&x,&y); if(ceng[x]>ceng[y]) printf("%d %d\n",y,x); else printf("%d %d\n",x,y); } return 0; }

[模擬賽] T2 混合圖