[CEOI2017]One-Way Streets
题目大意:
给你一个无向图,现在告诉你一些点对(u,v),
要你在保证从u到v的所有路径都不变的情况下,尽可能把所有的边变成单向边,
问你可以唯一确定哪些边的方向,以及方向是从u到v还是从v到u。
思路:
首先不难发现环上的边都不能确定方向,所以我们可以先缩环。
缩环以后剩下的图就变成了一棵树,考虑对树进行一些操作来确定边的方向。
我们可以树链剖分,用线段树维护边的方向,
但是树上边的方向不一定都是同一种,因此我们可以先不考虑从u到v还是从v到u。
我们只需要先维护从上到下还是从下到上。
如果维护时发现当前维护的边的区间已经是有向的,而且和当前方向相反,那么就是双向边。
最后统计答案时,只需要判一下u在上还是v在上即可。
小优化:当维护区间已经是双向时,不管怎样它永远都是双向了,我们可以直接在线段树上剪枝。
1 #include<stack> 2 #include<cstdio> 3 #include<cctype> 4 #include<vector> 5 inline int getint() { 6 register char ch; 7 while(!isdigit(ch=getchar())); 8 register int x=ch^'0'; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 10 return x; 11 } 12 const int N=100001,M=100001; 13 struct Edge2 { 14 int u,v; 15 }; 16 Edge2 edge[M]; 17 struct Edge { 18 int to,id; 19 }; 20 std::vector<Edge> e[N]; 21 inline void add_edge(const int &u,const int &v,const int &id) { 22 e[u].push_back((Edge){v,id}); 23 e[v].push_back((Edge){u,id}); 24 } 25 char type[M]; 26 std::stack<int> s; 27 bool mark[M],ins[N]; 28 int dfn[N],low[N],bcc[N]; 29 void tarjan(const int &x) { 30 s.push(x); 31 ins[x]=true; 32 dfn[x]=low[x]=++dfn[0]; 33 for(unsigned i=0;i<e[x].size();i++) { 34 const int &y=e[x][i].to,&id=e[x][i].id; 35 if(mark[id]) continue; 36 mark[id]=true; 37 if(!dfn[y]) { 38 tarjan(y); 39 low[x]=std::min(low[x],low[y]); 40 } else if(ins[y]) { 41 low[x]=std::min(low[x],dfn[y]); 42 } 43 } 44 if(dfn[x]==low[x]) { 45 bcc[0]++; 46 int y=0; 47 while(y!=x) { 48 y=s.top(); 49 s.pop(); 50 ins[y]=false; 51 bcc[y]=bcc[0]; 52 } 53 } 54 } 55 int par[N],size[N],dep[N],son[N],top[N],id[N],ori[N]; 56 void dfs1(const int &x,const int &par) { 57 size[x]=1; 58 ::par[x]=par; 59 dep[x]=dep[par]+1; 60 for(unsigned i=0;i<e[x].size();i++) { 61 const int &y=e[x][i].to; 62 if(y==par) continue; 63 dfs1(y,x); 64 size[x]+=size[y]; 65 if(size[y]>size[son[x]]) son[x]=y; 66 } 67 } 68 void dfs2(const int &x) { 69 if(x==son[par[x]]) { 70 top[x]=top[par[x]]; 71 } else { 72 top[x]=x; 73 } 74 if(son[x]) { 75 id[son[x]]=++id[0]; 76 dfs2(son[x]); 77 } 78 for(unsigned i=0;i<e[x].size();i++) { 79 const int &y=e[x][i].to; 80 if(y!=par[x]&&y!=son[x]) { 81 id[y]=++id[0]; 82 dfs2(y); 83 } 84 ori[id[y]]=e[x][i].id; 85 } 86 } 87 class SegmentTree { 88 #define _left <<1 89 #define _right <<1|1 90 private: 91 char val[N<<2]; 92 void push_down(const int &p) { 93 if(!val[p]) return; 94 if(val[p _left]) { 95 if(val[p _left]!=val[p]) val[p]='B'; 96 } else { 97 val[p _left]=val[p]; 98 } 99 if(val[p _right]) { 100 if(val[p _right]!=val[p]) val[p]='B'; 101 } else { 102 val[p _right]=val[p]; 103 } 104 } 105 public: 106 void modify(const int &p,const int &b,const int &e,const int &l,const int &r,const char &c) { 107 if(val[p]=='B') return; 108 if(b==l&&e==r) { 109 if(val[p]) { 110 if(val[p]!=c) val[p]='B'; 111 } else { 112 val[p]=c; 113 } 114 return; 115 } 116 push_down(p); 117 const int mid=(b+e)>>1; 118 if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r),c); 119 if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r,c); 120 } 121 void stat(const int &p,const int &b,const int &e) { 122 if(val[p]=='B') return; 123 if(b==e) { 124 if(val[p]) { 125 type[ori[b]]=val[p]; 126 } else { 127 type[ori[b]]='B'; 128 } 129 return; 130 } 131 push_down(p); 132 const int mid=(b+e)>>1; 133 stat(p _left,b,mid); 134 stat(p _right,mid+1,e); 135 } 136 #undef _left 137 #undef _right 138 }; 139 SegmentTree t; 140 void modify(int x,int y) { 141 char c='R',c0='L'; 142 while(top[x]!=top[y]) { 143 if(dep[top[x]]<dep[top[y]]) { 144 std::swap(x,y); 145 std::swap(c,c0); 146 } 147 t.modify(1,1,bcc[0],id[top[x]],id[x],c); 148 x=par[top[x]]; 149 } 150 if(x==y) return; 151 if(dep[x]<dep[y]) { 152 std::swap(x,y); 153 std::swap(c,c0); 154 } 155 t.modify(1,1,bcc[0],id[son[y]],id[x],c); 156 } 157 int main() { 158 const int n=getint(),m=getint(); 159 for(register int i=1;i<=m;i++) { 160 edge[i]=(Edge2){getint(),getint()}; 161 add_edge(edge[i].u,edge[i].v,i); 162 } 163 for(register int i=1;i<=n;i++) { 164 if(!dfn[i]) tarjan(i); 165 e[i].clear(); 166 } 167 for(register int i=1;i<=m;i++) { 168 const int &u=edge[i].u,&v=edge[i].v; 169 if(bcc[u]==bcc[v]) { 170 type[i]='B'; 171 continue; 172 } 173 add_edge(bcc[u],bcc[v],i); 174 } 175 for(register int i=1;i<=bcc[0];i++) { 176 if(!size[i]) { 177 dfs1(i,0); 178 id[i]=++id[0]; 179 dfs2(i); 180 } 181 } 182 for(register int q=getint();q;q--) { 183 const int x=bcc[getint()],y=bcc[getint()]; 184 modify(x,y); 185 } 186 t.stat(1,1,bcc[0]); 187 for(register int i=1;i<=m;i++) { 188 const int &u=bcc[edge[i].u],&v=bcc[edge[i].v]; 189 if(type[i]!='B'&&dep[u]<dep[v]) { 190 if(type[i]=='L') { 191 type[i]='R'; 192 } else { 193 type[i]='L'; 194 } 195 } 196 } 197 puts(&type[1]); 198 return 0; 199 }