有两种做法,都比较好想。
首先,两种方法都要对于整个图求桥,因为边双连通分量中的两个点一定可以互达。
然后对于桥,我们得到一棵树(将所有的点所对应的连通分量标记好)。
第一种:
任意提一个结点,转成有根树,对于两个城市,求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;
}