[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 }

 

posted @ 2017-12-28 14:37  skylee03  阅读(166)  评论(0编辑  收藏  举报