• 【2016北京集训测试赛】river


    HINT

    注意是全程不能经过两个相同的景点,并且一天的开始和结束不能用同样的交通方式。

    [吐槽]

      嗯。。看到这题的想法的话。。先想到了每个点的度为2,然后就有点不知所措了

      隐隐约约想到了网络流,但并没有继续往下想了。。。

      听完学长的讲评之后(%xj)个人觉得建图还是很有意思的ovo

    [题解]

      因为每个点到对面都有k种方式,那就想到每个点原来的点$x_0$拆成k个点$x_1$, $x_2$, $x_3$... $x_k$

      然后很自然地$x_0$和拆成的点之间要连边

      容量的话,因为hint里面的限制,也就是说一个点到另一个点的k中交通方式中只能选一种

      (因为每个点只能到一次,而开始和结束不能用同样的方式)

      这样一来容量显然就应该是1了

      两岸之间的连接,就直接按照读入左岸连到右岸就好,容量也为1

      (但其实因为左岸的流入流量和右岸的流出流量都有限制,中间的那条好像容量取1~ $infty$都可以。。。%yxq)

      接着考虑最后的答案是怎么得到的,会发现其实我们最后的到的路线是若干个环,每个点的度为2(一个大概长这样的)

      

      如此一来,就会有个大胆的想法

      对于每一个左岸的$x_0$,我们连一条源点到它的容量为2的边

      对于每一个右岸的$x_0$,我们连一条它到汇点的容量为2的边

      这样起到一个限制了每个点的度的作用,就可以保证有环并且环内每个点的度都为2(个人感觉这点是很有意思的)

      

      于是乎最终的到的图长这样(以样例为例)

      

      那么现在考虑构造方案

      看回之前建图的思路,很容易得到的一个结论是满流的边肯定就是要走的边

      那么现在问题就变成知道一堆边然后构造方案啦

      很简单粗暴的方法直接强行把每个环走一遍记录下答案就好

      天数的话就看有多少个环就好啦

      挫挫的代码qwq

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<queue>
      5 #define inf 2147483647
      6 using namespace std;
      7 const int MAXN=50*6*2+10;
      8 struct xxx
      9 {
     10     int y,next,op,r,x;
     11 }a[MAXN*2];
     12 queue<int> q;
     13 int h[MAXN],lv[MAXN],id[110][10],num[MAXN];
     14 int go[MAXN][2],ans[110][110];
     15 bool vis[MAXN];
     16 int n,m,k,vs,vt,tot,tot1;
     17 int add(int x,int y,int r);
     18 int bfs();
     19 int dfs(int v,int o);
     20 int get_ans();
     21 
     22 int main()
     23 {
     24     freopen("a.in","r",stdin);
     25 
     26     int x,y,z;
     27     scanf("%d%d%d",&n,&m,&k);
     28     memset(h,-1,sizeof(h));
     29     tot=0;
     30     vs=0,vt=MAXN-1;
     31     for (int i=1;i<=n+n;++i)
     32         for (int j=0;j<=k;++j)
     33             id[i][j]=++tot,num[tot]=i;
     34     tot=0;
     35     for (int i=1;i<=n;++i)
     36     {
     37         add(vs,id[i][0],2);
     38         add(id[i+n][0],vt,2);
     39         for (int j=1;j<=k;++j)
     40             add(id[i][0],id[i][j],1),add(id[i+n][j],id[i+n][0],1);
     41     }
     42     for (int i=1;i<=m;++i)
     43     {
     44         scanf("%d%d%d",&x,&y,&z);
     45         add(id[x][z],id[y+n][z],1);
     46     }
     47     while (bfs()) dfs(vs,inf);
     48     get_ans();
     49 }
     50 
     51 int add(int x,int y,int r)
     52 {
     53     a[++tot].y=y; a[tot].next=h[x]; h[x]=tot; a[tot].r=r; a[tot].op=tot+1;
     54     a[++tot].y=x; a[tot].next=h[y]; h[y]=tot; a[tot].r=0; a[tot].op=tot-1;
     55 }
     56 
     57 int bfs()
     58 {
     59     while (!q.empty()) q.pop();
     60     memset(lv,0,sizeof(lv));
     61     q.push(vs);
     62     lv[vs]=1;
     63     int v,u;
     64     while (!q.empty())
     65     {
     66         v=q.front(); q.pop();
     67         for (int i=h[v];i!=-1;i=a[i].next)
     68         {
     69             u=a[i].y;
     70             if (lv[u]||!a[i].r) continue;
     71             q.push(u);
     72             lv[u]=lv[v]+1;
     73             if (u==vt) return true;
     74         }
     75     }
     76     return false;
     77 }
     78 
     79 int dfs(int v,int o)
     80 {
     81     if (v==vt||o==0) return o;
     82     int u,flow,ret=0;
     83     for (int i=h[v];i!=-1;i=a[i].next)
     84     {
     85         u=a[i].y;
     86         if (lv[u]!=lv[v]+1) continue;
     87         flow=dfs(u,min(a[i].r,o));
     88         if (flow)
     89         {
     90             a[i].r-=flow;
     91             a[a[i].op].r+=flow;
     92             ret+=flow;
     93             o-=flow;
     94             if (!o) break;
     95         }
     96     }
     97     return ret;
     98 }
     99 
    100 int get_ans()
    101 {
    102     int x,y,pre;
    103     //go[i]记录与i相连的两个点 
    104     for (int i=1;i<=n;++i)
    105         for (int j=1;j<=k;++j)
    106             for (int tmp=h[id[i][j]];tmp!=-1;tmp=a[tmp].next)
    107             {
    108                 if (a[tmp].r||a[tmp].y==id[i][0]) continue;
    109                 y=num[a[tmp].y];
    110                 if (!go[i][0]) go[i][0]=y;
    111                 else go[i][1]=y;
    112 
    113                 if (!go[y][0]) go[y][0]=i;
    114                 else go[y][1]=i;
    115             }
    116     memset(vis,false,sizeof(vis));
    117     int cnt=0;
    118     for (int i=1;i<=n;++i)
    119     {
    120         if (vis[i]) continue;
    121         ++cnt;
    122         //将每个环走一遍 
    123         pre=i,x=go[i][0]; 
    124         ans[cnt][++ans[cnt][0]]=i;
    125         vis[i]=true;
    126         while (x!=i)
    127         {
    128             vis[x]=true;
    129             ans[cnt][++ans[cnt][0]]=x;
    130             if (pre==go[x][0]) pre=x,x=go[x][1];
    131             else pre=x,x=go[x][0];
    132         }
    133         ans[cnt][++ans[cnt][0]]=x;
    134     }
    135     printf("%d
    ",cnt);
    136     //因为建图的方式所以左右岸肯定是交错来的 
    137     for (int i=1;i<=cnt;++i)
    138     {
    139         printf("%d ",ans[i][0]);
    140         for (int j=1;j<=ans[i][0];++j)
    141             if (j&1) printf("L%d ",ans[i][j]);
    142             else printf("R%d ",ans[i][j]-n);
    143         printf("
    ");
    144     }
    145 }
    View Code
  • 相关阅读:
    JVM-Java程序性能监控-初级篇
    一段获取app性能指标的py脚本
    一段从TXT导入excel的py脚本
    matplotlib根据Y轴数量伸缩画图的py脚本
    jsonpath读取json数据格式公用方法!!!
    python安装插件包注意事项
    Jenkins持续集成
    Jenkins简介&邮箱配置
    unittest框架扩展(基于代码驱动)自动化-下
    unittest框架扩展(自动生成用例)自动化-上
  • 原文地址:https://www.cnblogs.com/yoyoball/p/7451306.html
Copyright © 2020-2023  润新知