zoukankan      html  css  js  c++  java
  • [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 }
  • 相关阅读:
    mysql 数据库字符集问题
    适配器模式
    thinkphp学习笔记
    StarDict
    dereferencing pointer to incomplete type
    转载的一篇 关于git的
    策略模式
    让你的Ubuntu看的更顺眼些
    vim 配置
    .NET WEB SERVICE 学习记录
  • 原文地址:https://www.cnblogs.com/skylee03/p/8135585.html
Copyright © 2011-2022 走看看