• 2018沈阳网赛F--上下界网络流


    建图:

    首先加一个源点s和汇点t,分别连接在二分图的左边和右边,每条弧的上下界为【L, R】,二分图左边和右边之间连弧上下界为【0,1】,其实就相当于连弧为1。

    然后问题就转换为:有源汇最大流。

    继续建图:

    建立弧<t,s><,容量下界为00,上界为∞。

    加一个超级源ss和超级汇tt

    对于所有有上下界的弧(也就是s,t分别连接左边和右边的弧)进行分边

    一条为<ss,v>,容量为L

    一条为<u,tt>>,容量为L

    一条为<u,v>,容量为R-L

    其中前两条弧一般称为附加弧。

    然后跑一遍最大流,如果ss所有的出边(或者是TT所有的入边)都满流,就输出Yes

    以后再加图说明吧....

    (代码说明一下..   0为超级源,NV为超级汇,  NV-2为源, NV-1为汇)

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <queue>
      7 using namespace std;
      8 const int N = 5005;
      9 const int inf = 0x3f3f3f;
     10 
     11 struct Edge
     12 {
     13     int from,to,cap,flow;
     14     Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f) {}
     15 };
     16 
     17 struct Din
     18 {
     19     int s,t;
     20     vector<Edge>edges;
     21     vector<int>G[N];
     22     bool vis[N];
     23     int d[N];
     24     int cur[N];
     25 
     26     void addedge(int from,int to,int cap)
     27     {
     28         edges.push_back(Edge(from,to,cap,0));
     29         edges.push_back(Edge(to,from,0,0));
     30         int  m=edges.size();
     31         G[from].push_back(m-2);
     32         G[to].push_back(m-1);
     33     }
     34 
     35     bool bfs()
     36     {
     37         memset(vis,0,sizeof(vis));
     38         queue<int>Q;
     39         Q.push(s);
     40         d[s]=0;
     41         vis[s]=1;
     42         while(!Q.empty())
     43         {
     44             int x=Q.front();
     45             Q.pop();
     46             for(int i=0; i<G[x].size(); i++)
     47             {
     48                 Edge&e=edges[G[x][i]];
     49                 if(!vis[e.to]&&e.cap>e.flow)
     50                 {
     51                     vis[e.to]=1;
     52                     d[e.to]=d[x]+1;
     53                     Q.push(e.to);
     54                 }
     55             }
     56         }
     57         return vis[t];
     58     }
     59 
     60     int dfs(int x,int a)
     61     {
     62         if(x==t||a==0)
     63             return a;
     64         int flow=0,f;
     65         for(int i=cur[x]; i<G[x].size(); i++)
     66         {
     67             Edge&e=edges[G[x][i]];
     68             if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0)
     69             {
     70                 e.flow += f;
     71                 edges[G[x][i]^1].flow -= f;
     72                 flow += f;
     73                 a -= f;
     74                 if(!a)
     75                     break;
     76             }
     77         }
     78         return flow;
     79     }
     80 
     81     int Maxflow(int s,int t)
     82     {
     83         this->s=s,this->t=t;
     84         int flow=0;
     85         while(bfs())
     86         {
     87             memset(cur,0,sizeof(cur));
     88             flow += dfs(s,inf);
     89         }
     90         return flow;
     91     }
     92 };
     93 
     94 int main()
     95 {
     96     int N,F,D;
     97     int cnt = 0;
     98     while(scanf("%d%d%d",&N,&F,&D) != EOF)
     99     {
    100         Din tmp;
    101         int flag = 1;
    102         int NV = N+F+2+1, NE=0;
    103         int a, b;
    104         int l, r;
    105         scanf("%d%d",&l, &r);
    106         for(int i=0; i<D; i++)
    107         {
    108             scanf("%d%d",&a, &b);
    109             tmp.addedge(a,N+b, 1);
    110         }
    111         for(int i=1; i<=N; i++)
    112         {
    113             tmp.addedge(NV-2,i, r-l);
    114             tmp.addedge(0,i, l);
    115             tmp.addedge(NV-2,NV, l);
    116         }
    117         for(int i=1; i<=F; i++)
    118         {
    119             tmp.addedge(N+i,NV-1, r-l);
    120             tmp.addedge(0,NV-1, l);
    121             tmp.addedge(N+i,NV, l);
    122         }
    123         tmp.addedge(NV-1,NV-2, inf);
    124         int tt = tmp.Maxflow(NE,NV);
    125         for(int i=0; i<tmp.G[0].size(); i++)
    126         {
    127             Edge &e=tmp.edges[tmp.G[0][i]];
    128             if(e.flow < l){
    129                 flag = 0;
    130                 break;
    131             }
    132         }
    133         cnt++;
    134         if(flag)
    135             printf("Case %d: Yes
    ", cnt);
    136         else
    137             printf("Case %d: No
    ", cnt);
    138     }
    139 }
    View Code
  • 相关阅读:
    Dockerfile 指令 VOLUME 介绍
    Spring boot(4)-应用打包部署
    Docker Dockerfile详解
    poj-1045(数学不好怪我咯)
    poj-3185-开关问题
    poj-1163-The Triangle
    归并排序(Merge Sort)
    交换排序—快速排序(Quick Sort)
    交换排序—冒泡排序(Bubble Sort)
    选择排序—堆排序(Heap Sort) 没看明白,不解释
  • 原文地址:https://www.cnblogs.com/flyuz/p/9610052.html
Copyright © 2020-2023  润新知