• hdu 3491(最小割+拆点)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3491

    思路:由于每个城市顶点都具有权值,所以对于每个城市拆成两个点u和所对应的u',之间连容量为w的边,S,H两点不会算在最小割中,所以将这两点拆点,拆点后容量为无穷,添加源点vs(0)和汇点vt(2*n+1),加边(vs,s,INF)和(t+n,vt,INF),对于两相连的城市,用其中一个点的第二个点去连另一个点的第一个点,边流量为无穷大,然后求解最大流即可.

    View Code
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 #define MAXN 222
     6 #define MAXM 222222
     7 #define inf 1<<30
     8 struct Edge{
     9     int v,cap,next;
    10 }edge[MAXM];
    11 
    12 int head[MAXN];
    13 int pre[MAXN];
    14 int cur[MAXN];
    15 int level[MAXN];
    16 int gap[MAXN];
    17 int NV,NE,n,m,vs,vt;
    18 
    19 void Insert(int u,int v,int cap,int cc=0){
    20     edge[NE].v=v;edge[NE].cap=cap;
    21     edge[NE].next=head[u];head[u]=NE++;
    22 
    23     edge[NE].v=u;edge[NE].cap=cc;
    24     edge[NE].next=head[v];head[v]=NE++;
    25 }
    26 
    27 
    28 int SAP(int vs,int vt){
    29     memset(pre,-1,sizeof(pre));
    30     memset(level,0,sizeof(level));
    31     memset(gap,0,sizeof(gap));
    32     for(int i=1;i<=NV;i++)cur[i]=head[i];
    33     int u=pre[vs]=vs,maxflow=0,aug=-1;
    34     gap[0]=NV;
    35     while(level[vs]<NV){
    36 loop:
    37         for(int &i=cur[u];i!=-1;i=edge[i].next){
    38             int v=edge[i].v;
    39             if(edge[i].cap&&level[u]==level[v]+1){
    40                 aug==-1?aug=edge[i].cap:aug=min(aug,edge[i].cap);
    41                 pre[v]=u;
    42                 u=v;
    43                 if(v==vt){
    44                     maxflow+=aug;
    45                     for(u=pre[u];v!=vs;v=u,u=pre[u]){
    46                         edge[cur[u]].cap-=aug;
    47                         edge[cur[u]^1].cap+=aug;
    48                     }
    49                     aug=-1;
    50                 }
    51                 goto loop;
    52             }
    53         }
    54         int minlevel=NV;
    55         for(int i=head[u];i!=-1;i=edge[i].next){
    56             int v=edge[i].v;
    57             if(edge[i].cap&&minlevel>level[v]){
    58                 cur[u]=i;
    59                 minlevel=level[v];
    60             }
    61         }
    62         gap[level[u]]--;
    63         if(gap[level[u]]==0)break;
    64         level[u]=minlevel+1;
    65         gap[level[u]]++;
    66         u=pre[u];
    67     }
    68     return maxflow;
    69 }
    70 
    71 int main(){
    72     int _case,num,u,v,s,t;
    73     scanf("%d",&_case);
    74     while(_case--){
    75         scanf("%d%d%d%d",&n,&m,&s,&t);
    76         NE=0,NV=2*n+2;
    77         vs=0,vt=2*n+1;
    78         memset(head,-1,sizeof(head));
    79         Insert(vs,s,inf);
    80         Insert(t+n,vt,inf);
    81         for(int i=1;i<=n;i++){
    82             scanf("%d",&num);
    83             if(i!=s&&i!=t){Insert(i,i+n,num);}
    84             else Insert(i,i+n,inf);
    85         }
    86         for(int i=1;i<=m;i++){
    87             scanf("%d%d",&u,&v);
    88             Insert(u+n,v,inf);
    89             Insert(v+n,u,inf);
    90         }
    91         printf("%d\n",SAP(vs,vt));
    92     }
    93     return 0;
    94 }
  • 相关阅读:
    个人技术博客(α)
    git常用命令合集
    软件工程实践2017第二次结对作业
    软件工程实践2017第一次结对作业
    软件工程实践2017第二次作业
    软件工程实践2017第一次作业
    学习总结
    约瑟夫
    今天是星期几
    斐波那契数列取石子游戏
  • 原文地址:https://www.cnblogs.com/wally/p/3062522.html
Copyright © 2020-2023  润新知