loj2480「CEOI2017」One-Way Streets(边双连通分量,树上差分)

题目描述
给定一张 n 个点 m 条边的无向图,现在想要把这张图定向。 有 p 个限制条件,每个条件形如(xi,yi)(xi,yi),表示在新的有向图当中,xixi要能够沿着一些边走到 yiyi。 现在请你求出,每条边的方向是否能够唯一确定。同时请给出这些能够唯一确定的边的方向。

输入格式
第一行两个空格隔开的正整数 n,m。 接下来 m 行,每行两个空格隔开的正整数ai,biai,bi,表示 ai,biai,bi之间有一条边。 接下来一行一个整数 p表示限制条件的个数。 接下来 p 行,每行两个空格隔开的正整数 xi,yixi,yi,描述一个(xi,yi)(xi,yi)的限制条件。

输出格式
输出一行一个长度为 m 的字符串,表示每条边的答案:

若第 i 条边必须得要是 aiai指向 bibi 的,那么这个字符串的第i个字符应当为 R;
若第 i 条边必须得要是bibi 指向 aiai 的,那么这个字符串的第i个字符应当为 L;
否则,若第 i 条边的方向无法唯一确定,那么这个字符串的第i个字符应当为 B。样例数据
input

5 6
1 2
1 2
4 3
2 3
1 3
5 1
2
4 5
1 3
output

BBRBBL
数据规模与约定
对于所有测试点,有1≤n,m,p≤100 000;1≤ai,bi,xi,yi≤n1≤n,m,p≤100000;1≤ai,bi,xi,yi≤n1≤n,m,p≤100 000;1≤ai,bi,xi,yi≤n1≤n,m,p≤100000;1≤ai,bi,xi,yi≤n。

子任务1(30%):有n,m≤1000;p≤100子任务1(30%):有n,m≤1000;p≤100;
子任务2(30%):有p≤100子任务2(30%):有p≤100;
子任务3(40%):无特殊限制子任务3(40%):无特殊限制。
时间限制:1s1s
空间限制:256MB256MB


边双缩点后查分

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define ll long long
namespace io {
	const int SIZE = (1 << 21) + 1;
	char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[55]; int f, qr;
	// getchar
	#define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
	// print the remaining part
	inline void flush () {
		fwrite (obuf, 1, oS - obuf, stdout);
		oS = obuf;
	}
	// putchar
	inline void putc (char x) {
		*oS ++ = x;
		if (oS == oT) flush ();
	}
	// input a signed integer
	template <class I>
	inline void gi (I &x) {
		for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;
		for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15); x *= f;
	}
	// print a signed integer
	template <class I>
	inline void print (I &x) {
		if (!x) putc ('0'); if (x < 0) putc ('-'), x = -x;
		while (x) qu[++ qr] = x % 10 + '0',  x /= 10;
		while (qr) putc (qu[qr --]);
	}
	//no need to call flush at the end manually!
	struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io :: gi;
using io :: putc;
using io :: print;
int n,m,Q;
int linkk[101000],t;
int dfn[101000],low[101000],tot;
int bel[101000],f[101000][21],dep[101000];
int bz1[101000],bz2[101000],out[101000];
bool inq[101000],vis[101000];
stack<int>st;
struct node{int n,y,id;}e[201000];
struct linei{int l,r;}q[101000];
inline int min(int a,int b){return a<b?a:b;}
void insert(int x,int y,int id){
	e[++t].y = y;e[t].n = linkk[x];e[t].id = id;linkk[x] = t;
	e[++t].y = x;e[t].n = linkk[y];e[t].id = id;linkk[y] = t;
}
void tarjan(int x,int fa){
	dfn[x] = low[x] = ++tot;st.push(x);inq[x] = true;
	for(int i = linkk[x];i;i = e[i].n) if((i^1) != fa){
		int y = e[i].y;
		if(!dfn[y]) {
			tarjan(y,i);
			low[x] = min(low[x],low[y]);
		}
		else if(inq[y]) low[x] = min(low[x],dfn[y]);
	}
	if(dfn[x] == low[x]){
		bel[0]++;
		while(st.top() != x){
			inq[st.top()] = false;
			bel[st.top()] = bel[0];
			st.pop();
		}
		inq[x] = false; bel[x] = bel[0]; st.pop();
	}
}
void init(){
	int x,y;t=1;
	gi(n); gi(m);
	rep(i,1,m) gi(x),gi(y) ,insert(x,y,i),q[i].l = x,q[i].r = y;
}
void dfs(int x,int fa){
	vis[x] = true;
	f[x][0] = fa; dep[x] = dep[fa]+1;
	rep(j,1,20) f[x][j] = f[f[x][j-1]][j-1];
	for(int i = linkk[x];i;i = e[i].n) if(e[i].y != fa && !vis[e[i].y]) dfs(e[i].y,x);
}
int lca(int x,int y){
	if(dep[x] < dep[y]) swap(x,y);
	repp(j,20,0) if(dep[f[x][j]] >= dep[y]) x = f[x][j];
	if(x == y) return x;
	repp(j,20,0) if(f[x][j] != f[y][j]) x = f[x][j],y = f[y][j];
	return f[x][0];
}
void dfs(int x){
	vis[x] = true;
	bool flag = true;
	for(int i = linkk[x];i;i = e[i].n) if(e[i].y != f[x][0]){
		int y = e[i].y;
		if(!vis[y]) dfs(y),flag = false;
		if(bz1[y] > 0) out[e[i].id] = (i&1) ? 1 : 2;
		if(bz2[y] > 0) out[e[i].id] = (i&1) ? 2 : 1;
		if(!flag) bz1[x] += bz1[y] , bz2[x] += bz2[y];
	}
}
int main(){
	init();
	rep(i,1,n) if(!dfn[i]) tarjan(i,0);
	memset(linkk,0,sizeof(linkk)); t = 1;
	rep(i,1,m) if(bel[q[i].l] != bel[q[i].r]) insert(bel[q[i].l],bel[q[i].r],i);
	rep(i,1,bel[0]) if(!vis[i]) dfs(i,0);
	gi(Q); int x,y,z;
	rep(i,1,Q){
		gi(x); gi(y); x = bel[x];y = bel[y]; if(x == y) continue; z = lca(x,y);
		bz1[x]++;bz1[z]--; bz2[y]++;bz2[z]--;
	}
	memset(vis,0,sizeof(vis));
	rep(i,1,bel[0]) if(!vis[i]) dfs(i);
	rep(i,1,m) if(out[i] == 0) printf("%c",'B');
	else if(out[i] == 1) printf("%c",'R');
	else if(out[i] == 2) printf("%c",'L');
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值