有兩種做法,都比較好想。
首先,兩種方法都要對於整個圖求橋,因爲邊雙連通分量中的兩個點一定可以互達。
然後對於橋,我們得到一棵樹(將所有的點所對應的連通分量標記好)。
第一種:
任意提一個結點,轉成有根樹,對於兩個城市,求LCA,因爲有解,到LCA的路徑上的邊的方向是指向LCA的,另一邊相反,這個要注意遞歸處理(已經處理過的要跳過),不能O(N)更新方向。
第二種:
記錄每個聯通分量中出發和迴歸的點數。
對於每條橋,看左右端點的聯通分量點數,確定方向。
Code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int Max = 100000;
struct node{
int v, nxt, id;
}edge[(Max << 1) + 5];
struct line{
int s, t;
line(){}
line(int a, int b){s = a, t = b;}
}L[(Max << 1) + 5];
int N, M, P, bn;
char CC[] = {'B', 'R', 'L'};
int cnt = 1, Dfs_Clock;
int fir[Max + 5], Dfn[Max + 5], Low[Max + 5];
int Cnt[Max + 5][2], Po[Max + 5], Bcc[Max + 5], An[Max + 5];
bool Iscut[(Max << 1) + 5], vis[Max + 5];
bool getint(int & num){
char c; int flg = 1; num = 0;
while((c = getchar()) < '0' || c > '9'){
if(c == '-') flg = -1;
if(c == -1) return 0;
}
while(c >= '0' && c <= '9'){
num = num * 10 + c - 48;
if((c = getchar()) == -1)return 0;
}
num *= flg;
return 1;
}
void addedge(int a, int b, int id){
edge[++ cnt].v = b, edge[cnt].id = id, edge[cnt].nxt = fir[a], fir[a] = cnt;
}
void Tarjan(int u, int ff){
Dfn[u] = Low[u] = ++ Dfs_Clock;
for(int i = fir[u]; i; i = edge[i].nxt){
int v = edge[i].v;
if(! Dfn[v]){
Tarjan(v, i);
Low[u] = min(Low[u], Low[v]);
if(Low[v] > Dfn[u])
Iscut[edge[i].id] = 1;
}
else if(i != (ff ^ 1))
Low[u] = min(Low[u], Dfn[v]);
}
}
void Dfs(int u){
Bcc[u] = bn;
Po[bn] += Cnt[u][0];
Po[bn] -= Cnt[u][1];
for(int i = fir[u]; i; i = edge[i].nxt) if(! Bcc[edge[i].v] && ! Iscut[edge[i].id])
Dfs(edge[i].v);
}
int Get_sum(int u, int ff){
int rt = Po[u];
vis[u] = 1;
for(int i = fir[u]; i; i = edge[i].nxt) if(edge[i].v != ff){
int v = edge[i].v;
int sum = Get_sum(v, u);
if(sum != 0){
if((sum < 0) ^ (Bcc[L[edge[i].id].s] == edge[i].v))
An[edge[i].id] = 1;
else An[edge[i].id] = 2;
}
rt += sum;
}
return rt;
}
int main(){
freopen("oneway.in", "r", stdin);
freopen("oneway.out", "w", stdout);
getint(N), getint(M);
int u, v;
for(int i = 1; i <= M; ++ i)
getint(u), getint(v),
addedge(u, v, i), addedge(v, u, i),
L[i] = line(u, v);
for(int i = 1; i <= N; ++ i) if(! Dfn[i])
Tarjan(i, 0);
getint(P);
for(int i = 1; i <= P; ++ i){
getint(u), getint(v);
++ Cnt[u][0], ++ Cnt[v][1];
}
for(int i = 1; i <= N; ++ i) if(! Bcc[i])
++ bn, Dfs(i);
cnt = 0;
memset(fir, 0, sizeof fir );
memset(vis, 0, sizeof vis );
for(int i = 1; i <= M; ++ i) if(Iscut[i])
addedge(Bcc[L[i].s], Bcc[L[i].t], i),
addedge(Bcc[L[i].t], Bcc[L[i].s], i);
for(int i = 1; i <= bn; ++ i) if(! vis[i])
Get_sum(i, 0);
for(int i = 1; i <= M; ++ i)
if(! Iscut[i]) printf("B");
else printf("%c", CC[An[i]]);
return 0;
}