zoukankan      html  css  js  c++  java
  • hdu 4309(最大流+枚举状态)

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

    思路:2^12枚举修复哪些桥,不修复的桥没有花费,连接的边流量为1,要修复的桥则计算花费,边的流量为无穷,建立最大流模型来求解,增加一个源点S(0),和一个汇点T(n+1)。S向每个有人的点,连一条容量为人数的边,图中普通的u->v的有向边,连一条u->v的流量为无穷的边,对于u->v的隧道,可以连接u->v的流量无穷的边,和u->T的流量为隧道人数上限的边,求解最大流即可;

    ps:枚举状态用递归即可。

    View Code
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 using namespace std;
      5 #define MAXN 222
      6 #define MAXM 3333
      7 #define inf 1<<30
      8 
      9 struct Edge{
     10     int v,cap,next;
     11 }edge[MAXM],E[MAXM];
     12 
     13 struct ReEdge{
     14     int index,cap;
     15 }reedge[MAXM];
     16 
     17 int head[MAXN];
     18 int cur[MAXN];
     19 int pre[MAXN];
     20 int level[MAXN];
     21 int gap[MAXN];
     22 int NV,NE,vs,vt,n,m,total,mincost,maxnum;
     23 
     24 void Insert(int u,int v,int cap,int cc=0){
     25     edge[NE].v=v;edge[NE].cap=cap;
     26     edge[NE].next=head[u];head[u]=NE++;
     27 
     28     edge[NE].v=u;edge[NE].cap=cc;
     29     edge[NE].next=head[v];head[v]=NE++;
     30 }
     31 
     32 
     33 int SAP(int vs,int vt){
     34     memset(pre,-1,sizeof(pre));
     35     memset(level,0,sizeof(level));
     36     memset(gap,0,sizeof(gap));
     37     for(int i=0;i<=n+1;i++)cur[i]=head[i];
     38     int u=pre[vs]=vs,maxflow=0,aug=-1;
     39     gap[0]=NV;
     40     while(level[vs]<NV){
     41 loop:
     42         for(int &i=cur[u];i!=-1;i=edge[i].next){
     43             int v=edge[i].v;
     44             if(edge[i].cap&&level[u]==level[v]+1){
     45                 aug==-1?aug=edge[i].cap:aug=min(aug,edge[i].cap);
     46                 pre[v]=u;
     47                 u=v;
     48                 if(v==vt){
     49                     maxflow+=aug;
     50                     for(u=pre[u];v!=vs;v=u,u=pre[u]){
     51                         edge[cur[u]].cap-=aug;
     52                         edge[cur[u]^1].cap+=aug;
     53                     }
     54                     aug=-1;
     55                 }
     56                 goto loop;
     57             }
     58         }
     59         int minlevel=NV;
     60         for(int i=head[u];i!=-1;i=edge[i].next){
     61             int v=edge[i].v;
     62             if(edge[i].cap&&minlevel>level[v]){
     63                 cur[u]=i;
     64                 minlevel=level[v];
     65             }
     66         }
     67         gap[level[u]]--;
     68         if(gap[level[u]]==0)break;
     69         level[u]=minlevel+1;
     70         gap[level[u]]++;
     71         u=pre[u];
     72     }
     73     return maxflow;
     74 }
     75 
     76 
     77 void Solve(int num,int cost){
     78     if(num>=total){
     79         for(int i=0;i<NE;i+=2){
     80             edge[i].cap+=edge[i^1].cap;
     81             edge[i^1].cap=0;
     82         }
     83         int ans=SAP(vs,vt);
     84         if(ans>maxnum){maxnum=ans;mincost=cost;}
     85         else if(ans==maxnum&&mincost>cost){    mincost=cost;}
     86     }else {
     87         Solve(num+1,cost);
     88         edge[reedge[num].index].cap=inf;
     89         Solve(num+1,cost+reedge[num].cap);
     90         edge[reedge[num].index].cap=1;
     91         edge[reedge[num].index^1].cap=0;
     92     }
     93 }
     94 
     95 int main(){
     96     int city_num,u,v,w,p;
     97     while(~scanf("%d%d",&n,&m)){
     98         vs=0,vt=n+1,NV=n+2,NE=0,total=0,mincost=inf,maxnum=0;
     99         memset(head,-1,sizeof(head));
    100         for(int i=1;i<=n;i++){
    101             scanf("%d",&city_num);
    102             Insert(vs,i,city_num);
    103         }
    104         for(int i=1;i<=m;i++){
    105             scanf("%d%d%d%d",&u,&v,&w,&p);
    106             if(p==0)Insert(u,v,inf);
    107             else if(p<0){Insert(u,vt,w);Insert(u,v,inf);}
    108             else {
    109                 reedge[total].index=NE;
    110                 reedge[total++].cap=w;
    111                 Insert(u,v,1);
    112             }
    113         }
    114         Solve(0,0);
    115         if(!maxnum)puts("Poor Heaven Empire");
    116         else printf("%d %d\n",maxnum,mincost);
    117     }
    118     return 0;
    119 }
  • 相关阅读:
    pytest框架运用
    unitTest学习
    发送邮件
    python 连接远程服务器,修改时间
    Redis基础
    django 知识点扩展
    ACM 题目 1487: [蓝桥杯][算法提高VIP]不同单词个数统计
    Leetcode 面试题 08.01. 三步问题
    Leetocode 198. 打家劫舍
    Leetcode 121. 买卖股票的最佳时机
  • 原文地址:https://www.cnblogs.com/wally/p/3060832.html
Copyright © 2011-2022 走看看