[NOIP模拟赛]单向道路
来源:互联网 发布:王陆807和语料库 知乎 编辑:程序博客网 时间:2024/06/11 12:30
题目描述
一个国家有n个城市和m个双向道路连接他们。技术发展导致道路上行驶的车辆越来越多,越来越快,这导致出现问题:两辆相反方向行驶车辆的道路变得太窄。解决这一问题的方法是将所有道路转为单向道路。把道路改为单向会付出一些代价,例如以前可达的那些城市中的一些可能在更改后不再可达。政府编制了一系列重要的城市对,必须从第一个城市开始,到达第二个城市。你的任务是确定每条道路的方向,确保存在解决方案使得重要的城市对满足条件。对于某些道路,如果您想要获得解决方案,则无法选择道路的方向。车辆必须从第一个城市开向第二个城市(规定为向右的方向,由字母R表示),或者必须从第二个城市开向第一个(规定为向左的方向,用字母L表示)。然而,对于某些道路,存在某一个解决方案使得它的方向为左,而在另一个(可能是不同的)解决方案中它的方向为右。这时用两个方向的字母B来表示这些道路。
输入格式
第1行:2个整数表示n和m(1≤n,m,p ≤100000)
接下来m行,每行2个整数ai和bi,表示在城市ai和bi之间存在一条道路。在一对城市之间可能存在多条道路,而且一条道路可能连接同一个城市。接下来1行:1个整数p表示重要城市对的数量接下来p行,每行2个整数xi和yi,表示必须能够从xi出发,走到yi(1≤ai,bi,xi,yi≤n)
输出格式
输出一个长度为m的字符串,第i个字符应当为:
R 如果所有的解决方案中第i条道路都必须向右
L 如果所有的解决方案中第i条道路都必须向左B 如果某一个解决方案中第i条道路向左,而在另一个解决方案中它的方向为右
输入样例
5 6
1 2
1 2
4 3
2 3
1 3
5 1
2
4 51 3
输出样例
BBRBBL
样例说明
以第5条道路"1 3"为例,两个满足条件的解决方案是:LLRLRL 和RLRRLL,所以它的方向为B
题解:缩点+LCA
首先在环中的边一定是B。因此将环缩为点,使原图变为一棵树。再看重要城市对是否是同一个点,不是就找其LCA,标记重要城市对到LCA的路径。思路很简单,就是代码量有点大。
#include<cstdio>#include<algorithm>using namespace std;const int N=100005;const int M=N<<1;void Getin( int &shu ) {char c; int f=1; shu=0;for( c=getchar(); c<'0' || c>'9'; c=getchar() ) if( c=='-' ) f=-1;for( ; c>='0' && c<='9'; c=getchar() ) shu=shu*10+c-'0';shu*=f;}int fir[N], ecnt=1;struct enode{ int e, next; bool flg; } edge[M];void Elink( int s, int e ) {edge[++ecnt].e=e; edge[ecnt].next=fir[s]; fir[s]=ecnt;edge[++ecnt].e=s; edge[ecnt].next=fir[e]; fir[e]=ecnt;}int n, m, s, e;void Build_map() {Getin(n); Getin(m);for( int i=1; i<=m; i++ ) {Getin(s); Getin(e);if( s==e ) { ecnt+=2; continue; }Elink( s, e );}}int dfn[N], low[N], dfs_clock, pcnt;bool bri[M], vis[N];void Tarjan( int r, int laste ) {//找桥dfn[r]=low[r]=++dfs_clock;for( int i=fir[r]; i; i=edge[i].next )if( !dfn[ edge[i].e ] ) {Tarjan( edge[i].e, i );low[r]=min( low[r], low[ edge[i].e ] );if( dfn[r]<low[ edge[i].e ] ) bri[i]=bri[i^1]=1;}else if( i!=(laste^1) )low[r]=min( low[r], dfn[ edge[i].e ] );}void Note( int r, int id ) { low[r]=id; vis[r]=1; for( int i=fir[r]; i; i=edge[i].next ) if( !vis[ edge[i].e ] ) {if( bri[i] ) Note( edge[i].e, ++pcnt );else Note( edge[i].e, id );}}int point[N], tcnt, rot[N], rcnt, oppo[M];struct tnode{ int e, next; } tree[M];void Tlink( int s, int e ) {tree[++tcnt].e=e; tree[tcnt].next=point[s]; point[s]=tcnt;}void Build_tree() {//将原图缩点为一棵树for( int i=1; i<=n; i++ ) if( !dfn[i] ) {rot[++rcnt]=i; Tarjan( i, -1 );Note( i, ++pcnt );}for( int r=1; r<=n; r++ )for( int i=fir[r]; i; i=edge[i].next )if( low[r]!=low[ edge[i].e ] )Tlink( low[r], low[ edge[i].e ] ), oppo[tcnt]=i;//记录树中的边对应到原图的哪一条边}int fa[N], dep[N], siz[N], son[N];void DFS1( int r, int f, int d ) { dep[r]=d; siz[r]=1; for( int i=point[r]; i; i=tree[i].next )if( tree[i].e!=f ) {DFS1( tree[i].e, r, d+1 ); siz[r]+=siz[ tree[i].e ]; if( siz[ tree[i].e ]>siz[ son[r] ] ) son[r]=tree[i].e;fa[ tree[i].e ]=r;}}int top[N], fae[N], sc[N];void DFS2( int r, int f ) {sc[r]=r; if( son[r] ) top[ son[r] ]=top[r], DFS2( son[r], r ); for( int i=point[r]; i; i=tree[i].next ) if( tree[i].e!=f && tree[i].e!=son[r] ) { top[ tree[i].e ]=tree[i].e; DFS2( tree[i].e, r ); }else if( tree[i].e==f ) fae[r]=i;//记录当前点与其父亲点之间的边} int LCA( int p1, int p2 ) { while( top[p1]!=top[p2] ) { if( dep[ top[p1] ]>dep[ top[p2] ] ) p1=fa[ top[p1] ]; else p2=fa[ top[p2] ]; } return dep[p1]<dep[p2] ? p1 : p2; } void TCS() {for( int i=1; i<=rcnt; i++ ) { DFS1( low[ rot[i] ], -1, 1 ),top[ low[ rot[i] ] ]=low[ rot[i] ];DFS2( low[ rot[i] ], -1 );}}void Find_way() {TCS();int q; Getin(q);for( int i=1; i<=q; i++ ) {Getin(s); Getin(e);if( low[s]==low[e] ) continue;s=low[s]; e=low[e];int lca=LCA( s, e );while( s && s!=lca && dep[ sc[s] ]>dep[lca] ) { if( sc[s]!=s ) s=sc[s]; edge[ oppo[ fae[s] ] ].flg=1; sc[s]=lca; s=fa[s]; } while( e && e!=lca && dep[ sc[e] ]>dep[lca] ) { if( sc[e]!=e) e=sc[e]; edge[ oppo[ fae[e] ]^1 ].flg=1; sc[e]=lca; e=fa[e]; } }}void Print() {for( int i=2; i<=ecnt; i+=2 ) {if( edge[i].flg ) printf( "R" );else if( edge[i^1].flg ) printf( "L" );else printf( "B" );}putchar(10);}int main() {Build_map();Build_tree();Find_way();Print();return 0;}
阅读全文
0 0
- [NOIP模拟赛]单向道路
- #NOIP模拟赛#单向道路(LCA or 子树和-> 边的贡献)
- BSOJ3068 BZOJ2500 noip模拟赛 幸福的道路 树的最长链+单调队列 或 RMQ
- C++——NOIP模拟题——保留道路
- noip模拟赛 双城记
- 【noip模拟赛】密码
- 10.10NOIP模拟赛
- 10.08NOIP模拟赛
- 10.11NOIP模拟赛
- 10.12NOIP模拟赛
- 10.13NOIP模拟赛
- 【NOIP模拟赛】小奇挖矿
- NOIP模拟赛--军训
- 【NOIP模拟赛】数列
- noip模拟赛day8
- 16.1117 NOIP 模拟赛
- [NOIP模拟赛]单词
- [NOIP模拟赛]玻璃杯
- ArcGIS中的一些影像格式:.ige .img .rde .rrd
- 读取properties文件的内容值
- grunt压缩、合并css、js文件的配置信息
- 观察者模式和事件通知备忘
- python爬虫——获取图片2
- [NOIP模拟赛]单向道路
- 褚时健84岁再成亿万富翁
- JavaScript基础
- MySQL的InnoDB索引原理详解
- 界面编码报错:Page-encoding specified in XML prolog (UTF-8) is different from that specified in
- python学习十(多继承,多态,异常)
- Mybatis--更新
- Balanced Numbers 数位DP+3进制压缩
- 调用百度翻译接口demo(完整ajax请求)