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