zoukankan      html  css  js  c++  java
  • bzoj2502: 清理雪道(有源汇有上下界最小流)

    传送门

    别说话,自己看,我不会->这里

    我这里用的建图方法是先跑一次最大流,连上$(t,s,inf)$之后再跑一遍,然后答案就是之前连的那条边的反向边的流量

    据说还有种方法是连上$(t,s,inf)$之后跑一遍,记录这条边反向边流量,再拆掉边以及$ss$和$tt$,然后再跑一次最大流,答案就是之前记录的流量减去这次的流量。亲测差不多

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<queue>
     6 #define inf 0x3f3f3f3f
     7 using namespace std;
     8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     9 char buf[1<<21],*p1=buf,*p2=buf;
    10 inline int read(){
    11     #define num ch-'0'
    12     char ch;bool flag=0;int res;
    13     while(!isdigit(ch=getc()))
    14     (ch=='-')&&(flag=true);
    15     for(res=num;isdigit(ch=getc());res=res*10+num);
    16     (flag)&&(res=-res);
    17     #undef num
    18     return res;
    19 }
    20 const int N=505,M=100005;
    21 int head[N],Next[M],ver[M],edge[M],tot=1;
    22 int cur[N],dep[N],S,T;
    23 queue<int> q;
    24 inline void add(int u,int v,int e){
    25     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;
    26     ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=0;
    27 }
    28 bool bfs(){
    29     memset(dep,-1,sizeof(dep));
    30     memcpy(cur,head,sizeof(head));
    31     while(!q.empty()) q.pop();
    32     q.push(S),dep[S]=0;
    33     while(!q.empty()){
    34         int u=q.front();q.pop();
    35         for(int i=head[u];i;i=Next[i]){
    36             int v=ver[i];
    37             if(dep[v]<0&&edge[i]){
    38                 dep[v]=dep[u]+1,q.push(v);
    39                 if(v==T) return true;
    40             }
    41         }
    42     }
    43     return false;
    44 }
    45 int dfs(int u,int limit){
    46     if(u==T||!limit) return limit;
    47     int flow=0,f;
    48     for(int i=cur[u];i;cur[u]=i=Next[i]){
    49         int v=ver[i];
    50         if(dep[v]==dep[u]+1&&(f=dfs(v,min(limit,edge[i])))){
    51             flow+=f,limit-=f;
    52             edge[i]-=f,edge[i^1]+=f;
    53             if(!limit) break;
    54         }
    55     }
    56     if(!flow) dep[u]=-1;
    57     return flow;
    58 }
    59 int dinic(){
    60     int flow=0;
    61     while(bfs()) flow+=dfs(S,inf);
    62     return flow;
    63 }
    64 int n,s,t,k[N];
    65 int main(){
    66     //freopen("testdata.in","r",stdin);
    67     n=read();
    68     for(int i=1;i<=n;++i){
    69         int x=read();
    70         while(x--){
    71             int y=read();
    72             --k[i],++k[y];
    73             add(i,y,inf);
    74         }
    75     }
    76     s=0,t=n+1,S=n+2,T=n+3;
    77     for(int i=1;i<=n;++i)
    78     add(s,i,inf),add(i,t,inf);
    79     for(int i=1;i<=n;++i)
    80     k[i]<0?add(i,T,-k[i]):add(S,i,k[i]);
    81     dinic();
    82     add(t,s,inf);
    83     dinic();
    84     printf("%d
    ",edge[tot]);
    85     return 0;
    86 }
  • 相关阅读:
    由typedef和函数指针引起的危机
    从JVM角度看Java多态
    C语言中判断字符串str1是否以str2开始或结束
    Linux下利用json-c从一个json数组中提取每一个元素中的部分字段组成一个新json数组
    C语言中的条件编译
    学会 Python 到底能干嘛?我们整理出了 7 大工作方向……
    新手指南:我应该学哪种编程语言?
    盘点:2019年最赚钱的10种编程语言
    11个提升编程能力的小方法
    收好这份 Vue 升级图,假期偷偷上个钻
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9584569.html
Copyright © 2011-2022 走看看