题目描述
给定一张 n n n 个点 m m m 条边的无向图,现在想要把这张图定向。
有 p p p 个限制条件,每个条件形如 ( x i , y i ) (x_i,y_i) (xi,yi),表示在新的有向图当中, x i x_i xi 要能够沿着一些边走到 y i y_i yi 。
现在请你求出,每条边的方向是否能够唯一确定。同时请给出这些能够唯一确定的边的方向。
输入输出格式
输入格式:
第一行两个空格隔开的正整数 n , m n,m n,m 。
接下来 m m m 行,每行两个空格隔开的正整数 a i , b i a_i,b_i ai,bi,表示 a i , b i a_i,b_i ai,bi 之间有一条边。
接下来一行一个整数 p p p,表示限制条件的个数。
接下来 p p p 行,每行两个空格隔开的正整数 x i , y i x_i,y_i xi,yi,描述一个 ( x i , y i ) (x_i,y_i) (xi,yi)的限制条件。
输出格式:
输出一行一个长度为 m m m 的字符串,表示每条边的答案:
若第 i i i 条边必须得要是 a i a_i ai指向 b i b_i bi 的,那么这个字符串的第 i i i 个字符应当为 R;
若第 i i i 条边必须得要是 b i b_i bi 指向 a i a_i ai 的,那么这个字符串的第 i i i个字符应当为 L;
否则,若第 i i i 条边的方向无法唯一确定,那么这个字符串的第 i i i 个字符应当为 B。
思路
可以得到一个的结论:在同一个双联通分量中的点之间的边方向无法确定。
所以可以缩点,然后得到一个森林。
对于要求的方向,多定义一个 a a a数组,对于起点 x x x, a [ x ] + + a[x]++ a[x]++,终点 y y y, a [ y ] − − a[y]-- a[y]−−。
每一点走向父节点的边方向可以记住 a a a来判断。
a < 0 a<0 a<0则应由父节点走向子节点
a > 0 a>0 a>0则应由子节点走向父节点
a = 0 a=0 a=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;
}