zoukankan      html  css  js  c++  java
  • Tourists Codeforces

    https://codeforces.com/contest/487/problem/E

    http://uoj.ac/problem/30

    显然割点走过去就走不回来了...可以看出题目跟点双有关

    有一个结论:如果在点双中有不同的点a,b,c,那么一定存在点不重复的路径从a到c再到b。

    证明(摘自https://codeforces.com/blog/entry/14832):

    显然这样的点双中,点数>=3,因此移除任意点或任意边,仍然连通

    新建一张网络流图。用边(u,v,w)表示从u到v容量为w的边

    对于原点双中每一条边(u,v),建新边(u,v,1),(v,u,1)

    新建点S,T,建边(S,c,2),(a,T,1),(b,T,1)

    用拆点的方法,给S,T,c外的每一个点1的容量(拆点过程略)

    此时,显然如果S到T的最大流为2,那么存在合法方案

    最大流=最小割。显然最小割<=2(割掉(a,T)与(b,T)的边)。割掉新图中任意一条权值为1的边(除(a,T),(b,T)),对应删除原点双的一条边或一个点,显然删除之后原图仍然连通,则新图也连通。因此最小割>1。所以最小割=2

    就是说,如果走的时候要穿过一个点双(任意点开始,任意点结束),那么一定可以找到一条合法路径经过点双内权值最小的点

    有一个想法:

    可以点双缩点成树(圆方树)(每个点双新建一个点,向点双中所有点连边,删除原图中所有边)

    (树中代表一个点双的点的权值是点双中点权的最小值)

    然后查询就是树上两点路径上最小值,修改就是单点修改(每个点双用一个multiset维护点双中所有点的权值。修改非割点就直接在它属于的点双的multiset中改,如果multiset中最小值变了就对应修改维护最小值的数据结构;修改割点方法在后面),用树剖维护即可

    好像还不怎么对。。割点也是属于点双的,但是修改割点权值显然不能暴力修改其属于的所有点双

    看了题解,方法是:每个割点就当做属于它在缩点树中的父亲(这个父亲一定代表一个点双;如果不存在父亲就不用维护),每次修改就在这个父亲的multiset那里改;同时每次查询的时候,如果两点的lca代表一个点双,那么除两点路径上最小值外还要考虑lca的父亲(一定是个割点;如果不存在父亲就不用额外查)

    然而真的码不动。。5K代码,续了一下午A掉

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<vector>
      5 #include<set>
      6 using namespace std;
      7 #define fi first
      8 #define se second
      9 #define mp make_pair
     10 #define pb push_back
     11 typedef long long ll;
     12 typedef unsigned long long ull;
     13 typedef pair<int,int> pii;
     14 struct E
     15 {
     16     int to,nxt;
     17 };
     18 int a[200010];
     19 int n,m,qq;
     20 namespace S
     21 {
     22 #define lc (num<<1)
     23 #define rc (num<<1|1)
     24 int d[800100];
     25 void setx(int L,int x,int l,int r,int num)
     26 {
     27     if(l==r)    {d[num]=x;return;}
     28     int mid=l+((r-l)>>1);
     29     if(L<=mid)    setx(L,x,l,mid,lc);
     30     else    setx(L,x,mid+1,r,rc);
     31     d[num]=min(d[lc],d[rc]);
     32 }
     33 int gmin(int L,int R,int l,int r,int num)
     34 {
     35     if(L<=l&&r<=R)    return d[num];
     36     int mid=l+((r-l)>>1);int ans=0x3f3f3f3f;
     37     if(L<=mid)    ans=min(ans,gmin(L,R,l,mid,lc));
     38     if(mid<R)    ans=min(ans,gmin(L,R,mid+1,r,rc));
     39     return ans;
     40 }
     41 int getmin(int L,int R,int l,int r,int num)
     42 {
     43     if(L>R)    swap(L,R);
     44     //printf("19t%d %d %d
    ",L,R,gmin(L,R,l,r,num));
     45     return gmin(L,R,l,r,num);
     46 }
     47 }
     48 int cnt;
     49 int bno[100010];
     50 bool iscut[100010];
     51 namespace T
     52 {
     53 E e[400100];
     54 int f1[200100],ne;
     55 void me(int x,int y)
     56 {
     57     e[++ne].to=y;e[ne].nxt=f1[x];f1[x]=ne;
     58     e[++ne].to=x;e[ne].nxt=f1[y];f1[y]=ne;
     59 }
     60 bool vis[200100];
     61 int sz[200100],hson[200100],tp[200100],dep[200100];
     62 void dfs1(int u,int fa)
     63 {
     64     sz[u]=1;
     65     vis[u]=1;
     66     for(int k=f1[u];k;k=e[k].nxt)
     67         if(e[k].to!=fa)
     68         {
     69             dep[e[k].to]=dep[u]+1;
     70             dfs1(e[k].to,u);
     71             sz[u]+=sz[e[k].to];
     72             if(sz[e[k].to]>sz[hson[u]])
     73                 hson[u]=e[k].to;
     74         }
     75 }
     76 int ar[200100],lp[200100],f[200100];
     77 void dfs2(int u,int fa)
     78 {
     79     ar[++ar[0]]=u;lp[u]=ar[0];
     80     f[u]=fa;
     81     if(u==hson[fa])    tp[u]=tp[fa];
     82     else    tp[u]=u;
     83     if(hson[u])    dfs2(hson[u],u);
     84     for(int k=f1[u];k;k=e[k].nxt)
     85         if(e[k].to!=fa&&e[k].to!=hson[u])
     86             dfs2(e[k].to,u);
     87 }
     88 multiset<int> s[100100];//s[i]维护i号点双里面所有非割点的权值
     89 void update2(int x)
     90 {
     91     a[x+n]=*s[x].begin();
     92     //printf("9t%d %d
    ",x,a[x+n]);
     93     S::setx(lp[x+n],a[x+n],1,n+cnt,1);
     94 }
     95 void change(int x,int y)
     96 {
     97     if(!iscut[x])
     98     {
     99         s[bno[x]].erase(s[bno[x]].find(a[x]));
    100         s[bno[x]].insert(a[x]=y);
    101         update2(bno[x]);
    102     }
    103     else
    104     {
    105         if(f[x])
    106         {
    107             s[f[x]-n].erase(s[f[x]-n].find(a[x]));
    108             s[f[x]-n].insert(y);
    109             update2(f[x]-n);
    110         }
    111         a[x]=y;
    112         S::setx(lp[x],y,1,n+cnt,1);
    113     }
    114 }
    115 int query(int x,int y)
    116 {
    117     if(x==y)    return a[x];
    118     //printf("99t%d %d
    ",x,y);
    119     //if(!iscut[x])    x=n+bno[x];
    120     //if(!iscut[y])    y=n+bno[y];
    121     int ans=0x3f3f3f3f;
    122     while(tp[x]!=tp[y])
    123     {
    124         if(dep[tp[x]]<dep[tp[y]])    swap(x,y);
    125         //printf("7t%d %d
    ",x,y);
    126         ans=min(ans,S::getmin(lp[x],lp[tp[x]],1,n+cnt,1));
    127         x=f[tp[x]];
    128     }
    129     ans=min(ans,S::getmin(lp[x],lp[y],1,n+cnt,1));
    130     if(dep[x]>dep[y])    swap(x,y);
    131     if(x>n&&f[x])    ans=min(ans,a[f[x]]);
    132     return ans;
    133 }
    134 void work()
    135 {
    136     int i;
    137     /*
    138     for(i=1;i<=n+cnt;i++)
    139         for(int k=f1[i];k;k=e[k].nxt)
    140             printf("1t%d %d
    ",i,e[k].to);
    141     for(i=1;i<=n;i++)
    142         printf("%d ",bno[i]);
    143     puts("t2");
    144     for(i=1;i<=n;i++)
    145         printf("%d ",int(iscut[i]));
    146     puts("t3");
    147     */
    148     for(i=1;i<=n+cnt;i++)
    149         if(!vis[i])
    150         {
    151             dfs1(i,0);
    152             dfs2(i,0);
    153         }
    154     /*
    155     for(i=1;i<=ar[0];i++)
    156         printf("%d ",ar[i]);
    157     puts("t4");
    158     for(i=1;i<=n+cnt;i++)
    159         printf("%d ",lp[i]);
    160     puts("t5");
    161     for(i=1;i<=n+cnt;i++)
    162         printf("6t%d %d
    ",f[i],tp[i]);
    163     */
    164     for(i=1;i<=n;i++)
    165         if(!iscut[i])
    166         {
    167             s[bno[i]].insert(a[i]);
    168             S::setx(lp[i],0x3f3f3f3f,1,n+cnt,1);
    169         }
    170         else
    171         {
    172             if(f[i])
    173             {
    174                 s[f[i]-n].insert(a[i]);
    175             }
    176             S::setx(lp[i],a[i],1,n+cnt,1);
    177         }
    178     for(i=1;i<=cnt;i++)
    179         update2(i);
    180     //for(i=1;i<=ar[0];i++)
    181     //    printf("16t%d
    ",S::getmin(i,i,1,n+cnt,1));
    182 }
    183 
    184 }
    185 namespace G
    186 {
    187 E e[200100];
    188 int f1[100010],ne=1;
    189 void me(int x,int y)
    190 {
    191     e[++ne].to=y;e[ne].nxt=f1[x];f1[x]=ne;
    192     e[++ne].to=x;e[ne].nxt=f1[y];f1[y]=ne;
    193 }
    194 int dfc,dfn[100010];
    195 pii st[100010];int tp;
    196 int dfs(int u,int last)
    197 {
    198     //printf("3t%d %d
    ",u,last);
    199     int k,v,lowu=dfn[u]=++dfc,chi=0,lowv;pii x;
    200     for(k=f1[u];k;k=e[k].nxt)
    201     {
    202         v=e[k].to;
    203         if(!dfn[v])
    204         {
    205             st[++tp]=mp(u,v);++chi;
    206             lowv=dfs(v,k);lowu=min(lowu,lowv);
    207             if(lowv>=dfn[u])
    208             {
    209                 //printf("4t%d %d
    ",u,v);
    210                 iscut[u]=1;
    211                 ++cnt;
    212                 for(;;)
    213                 {
    214                     x=st[tp--];
    215                     if(bno[x.fi]!=cnt)
    216                     {
    217                         bno[x.fi]=cnt;
    218                         T::me(n+cnt,x.fi);
    219                     }
    220                     if(bno[x.se]!=cnt)
    221                     {
    222                         bno[x.se]=cnt;
    223                         T::me(n+cnt,x.se);
    224                     }
    225                     if(x.fi==u&&x.se==v)    break;
    226                 }
    227             }
    228         }
    229         else if(dfn[v]<dfn[u]&&k!=(last^1))
    230         {
    231             st[++tp]=mp(u,v);
    232             lowu=min(lowu,dfn[v]);
    233         }
    234     }
    235     if(!last&&chi==1)    iscut[u]=0;
    236     //printf("5t%d %d %d
    ",u,lowu,dfn[u]);
    237     return lowu;
    238 }
    239 }
    240 
    241 
    242 int main()
    243 {
    244     char tmp[233];
    245     int i,x,y;
    246     scanf("%d%d%d",&n,&m,&qq);
    247     for(i=1;i<=n;i++)    scanf("%d",&a[i]);
    248     for(i=1;i<=m;i++)
    249     {
    250         scanf("%d%d",&x,&y);
    251         G::me(x,y);
    252     }
    253     for(i=1;i<=n;i++)
    254         if(!G::dfn[i])
    255             G::dfs(i,0);
    256     T::work();
    257     while(qq--)
    258     {
    259         scanf("%s%d%d",tmp,&x,&y);
    260         if(tmp[0]=='C')
    261         {
    262             T::change(x,y);
    263         }
    264         else
    265         {
    266             printf("%d
    ",T::query(x,y));
    267         }
    268     }
    269     return 0;
    270 }
    View Code
  • 相关阅读:
    虚拟机VMware 8安装Linux系统详细过程图解
    NSMutableArray 对象的一些方法
    NSString类中 哦见过的方法
    c语言的 地址运算符 & 和 指针运算符* 的区别
    const 静态的变量
    float scale = [[UIScreen mainScreen] scale]
    core Data 中 TIMESTAMP 类型
    NSPredicate
    xcode中解决 nslog 控制台 显示不出来
    按字符串读取文件内容NSString stringWithContentsOfFile: (NSString类方法)
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9803900.html
Copyright © 2011-2022 走看看