1. 程式人生 > >CEOI2017 One-Way Streets

CEOI2017 One-Way Streets

題目描述

給定一張 nn 個點 mm 條邊的無向圖,現在想要把這張圖定向。

pp 個限制條件,每個條件形如 (xi,yi)(x_i,y_i),表示在新的有向圖當中,xix_i 要能夠沿著一些邊走到 yiy_i ​​。

現在請你求出,每條邊的方向是否能夠唯一確定。同時請給出這些能夠唯一確定的邊的方向。

輸入輸出格式

輸入格式:

第一行兩個空格隔開的正整數 n,mn,m

接下來 mm 行,每行兩個空格隔開的正整數 ai,bia_i,b_i​​,表示 ai,bia_i,b_i​ 之間有一條邊。

接下來一行一個整數 p

p,表示限制條件的個數。

接下來 pp 行,每行兩個空格隔開的正整數 xi,yix_i,y_i,描述一個 (xi,yi)(x_i,y_i)的限制條件。

輸出格式:

輸出一行一個長度為 mm 的字串,表示每條邊的答案:

若第 ii 條邊必須得要是 aia_i指向 bib_i​ 的,那麼這個字串的第 ii 個字元應當為 R;

若第 ii 條邊必須得要是 bib_i ​ 指向 aia_i ​​ 的,那麼這個字串的第 ii個字元應當為 L;

否則,若第 ii 條邊的方向無法唯一確定,那麼這個字串的第 ii 個字元應當為 B。

思路

可以得到一個的結論:在同一個雙聯通分量中的點之間的邊方向無法確定。

所以可以縮點,然後得到一個森林。

對於要求的方向,多定義一個aa陣列,對於起點xxa[x]++a[x]++,終點yya[y]a[y]--

每一點走向父節點的邊方向可以記住aa來判斷。

a<0a<0則應由父節點走向子節點

a>0a>0則應由子節點走向父節點

a=0a=0則無法判斷方向。

程式碼

#include<cstdio>
#include<string>
#include<cstring>
#define R_ register inline int read() { int ret=0,f=1,ch=getchar(); for (; !isdigit(ch); ch=getchar()) if (ch=='-') f=-f; for (; isdigit(ch); ch=getchar()) ret=ret*10+ch-48; return ret*f; } const int maxn=2e5+5; struct edge {int son,nxt,id,s;} E[maxn],T[maxn]; int top,tar,cnt,sta[maxn],dfn[maxn],low[maxn],bel[maxn]; int N,M,P,tot=1,lnk[maxn],hed[maxn],Ans[maxn],vis[maxn],a[maxn]; inline void add_edge(int y,int x,int id) { E[++tot].son=y,E[tot].nxt=lnk[x],lnk[x]=tot,E[tot].id=id,E[tot].s=+1; E[++tot].son=x,E[tot].nxt=lnk[y],lnk[y]=tot,E[tot].id=id,E[tot].s=-1; } inline void Add_edge(int x,int y,int id,int s) { T[++tot].son=y,T[tot].nxt=hed[x],hed[x]=tot,T[tot].id=id,T[tot].s=s; } void tarjan(int x,int pre=0) { dfn[x]=low[x]=++cnt,sta[++top]=x; for (R_ int k=lnk[x],v; v=E[k].son,k; k=E[k].nxt) if (k^pre) if (!dfn[v]) { tarjan(v,k^1),low[x]=std::min(low[x],low[v]); if (low[v]>dfn[x]) { for (++tar; sta[top]^v; ) bel[sta[top]]=tar,--top; bel[sta[top]]=tar,--top; } } else low[x]=std::min(low[x],dfn[v]); } void dfs(int x,int fa,int id,int s) { for (R_ int k=hed[x],v; v=T[k].son,k; k=T[k].nxt) if (!vis[v]) vis[v]=1,dfs(v,x,T[k].id,T[k].s),a[x]+=a[v]; if (a[x]) Ans[id]=(a[x]*s<0?1:2); } int main() { R_ int i,k,x,y; for (N=read(),M=read(),i=1; i<=M; ++i) add_edge(read(),read(),i); for (i=1; i<=N; ++i) if (!dfn[i]) tarjan(i); if (top) for (++tar; top; --top) bel[sta[top]]=tar; for (tot=i=1; x=bel[i],i<=N; ++i) for (k=lnk[i]; y=bel[E[k].son],k; k=E[k].nxt) if (x^y) Add_edge(x,y,E[k].id,E[k].s); for (P=read(),i=1; i<=P; ++i) ++a[bel[read()]],--a[bel[read()]]; for (i=1; i<=tar; ++i) if (!vis[i]) vis[i]=1,dfs(i,0,0,0); for (i=1; i<=M; ++i) putchar(!Ans[i]?'B':(Ans[i]==1?'R':'L')); return 0; }