• poj 3204(最小割)


    题目链接:http://poj.org/problem?id=3204

    思路:显然只有增大那最小割边集上的边才能增加最大流,因此,我们可以先跑一遍最大流,然后对于那些满足条件的边u->v,当且仅当从源点开始沿着正向边能遍历到u,从汇点开始沿着正向边能遍历到v.

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<queue>
      6 using namespace std;
      7 #define MAXN 555
      8 #define MAXM 55555
      9 #define inf 1<<30
     10 
     11 struct Edge{
     12     int v,cap,next;
     13 }edge[MAXM];
     14 
     15 int n,m,NE,NV,vs,vt;
     16 int head[MAXN];
     17 
     18 void Insert(int u,int v,int cap)
     19 {
     20     edge[NE].v=v;
     21     edge[NE].cap=cap;
     22     edge[NE].next=head[u];
     23     head[u]=NE++;
     24 
     25     edge[NE].v=u;
     26     edge[NE].cap=0;
     27     edge[NE].next=head[v];
     28     head[v]=NE++;
     29 }
     30 
     31 int level[MAXN],gap[MAXN];
     32 void bfs(int vt)
     33 {
     34     memset(level,-1,sizeof(level));
     35     memset(gap,0,sizeof(gap));
     36     level[vt]=0;
     37     gap[level[vt]]++;
     38     queue<int>que;
     39     que.push(vt);
     40     while(!que.empty()){
     41         int u=que.front();
     42         que.pop();
     43         for(int i=head[u];i!=-1;i=edge[i].next){
     44             int v=edge[i].v;
     45             if(level[v]<0){
     46                 level[v]=level[u]+1;
     47                 gap[level[v]]++;
     48                 que.push(v);
     49             }
     50         }
     51     }
     52 }
     53 
     54 int pre[MAXN],cur[MAXN];
     55 int SAP(int vs,int vt)
     56 {
     57     bfs(vt);
     58     memset(pre,-1,sizeof(pre));
     59     memcpy(cur,head,sizeof(head));
     60     int maxflow=0;
     61     int u=pre[vs]=vs,aug=inf;
     62     gap[0]=NV;
     63     while(level[vs]<NV){
     64         bool flag=false;
     65         for(int &i=cur[u];i!=-1;i=edge[i].next){
     66             int v=edge[i].v;
     67             if(edge[i].cap>0&&level[u]==level[v]+1){
     68                 flag=true;
     69                 pre[v]=u;
     70                 u=v;
     71                 aug=min(aug,edge[i].cap);
     72                 if(v==vt){
     73                     maxflow+=aug;
     74                     for(u=pre[v];v!=vs;v=u,u=pre[u]){
     75                         edge[cur[u]].cap-=aug;
     76                         edge[cur[u]^1].cap+=aug;
     77                     }
     78                     aug=inf;
     79                 }
     80                 break;
     81             }
     82         }
     83         if(flag)continue;
     84         int minlevel=NV;
     85         for(int i=head[u];i!=-1;i=edge[i].next){
     86             int v=edge[i].v;
     87             if(edge[i].cap>0&&level[v]<minlevel){
     88                 minlevel=level[v];
     89                 cur[u]=i;
     90             }
     91         }
     92         if(--gap[level[u]]==0)break;
     93         level[u]=minlevel+1;
     94         gap[level[u]]++;
     95         u=pre[u];
     96     }
     97     return maxflow;
     98 }
     99 
    100 int vis[MAXN];
    101 void dfs1(int u)
    102 {
    103     vis[u]=1;
    104     for(int i=head[u];i!=-1;i=edge[i].next){
    105         int v=edge[i].v,cap=edge[i].cap;
    106         if(cap>0&&!vis[v])dfs1(v);
    107     }
    108 }
    109 
    110 void dfs2(int u)
    111 {
    112     vis[u]=2;
    113     for(int i=head[u];i!=-1;i=edge[i].next){
    114         int v=edge[i].v,cap=edge[i^1].cap;//注意是正向边容量
    115         if(cap>0&&!vis[v])dfs2(v);
    116     }
    117 }
    118 
    119 int main()
    120 {
    121     int u,v,w,ans;
    122     while(~scanf("%d%d",&n,&m)){
    123         NE=0;
    124         memset(head,-1,sizeof(head));
    125         vs=0,vt=n-1,NV=n;
    126         for(int i=1;i<=m;i++){
    127             scanf("%d%d%d",&u,&v,&w);
    128             Insert(u,v,w);
    129         }
    130         SAP(vs,vt);
    131         ans=0;
    132         memset(vis,0,sizeof(vis));
    133         dfs1(0);
    134         dfs2(n-1);
    135         for(int i=0;i<NE;i+=2){
    136             if(vis[edge[i].v]==2&&vis[edge[i^1].v]==1)ans++;
    137         }
    138         printf("%d
    ",ans);
    139     }
    140     return 0;
    141 }
    View Code
  • 相关阅读:
    【JVM源码解析】模板解释器解释执行Java字节码指令(下)
    【JVM源码解析】模板解释器解释执行Java字节码指令(上)
    【超硬核】JVM源码解读:Java方法main在虚拟机上解释执行
    Airtest结合tidevice实现IOS自动化测试
    Xcode连接真机提示设备未认证或版本太旧解决方案
    Jmeter——SMTP Sampler发送邮件
    Jmeter——脱离Jenkins后,Ant集成邮件通知
    spring boot快速入门
    MyBatisPlus 快速入门
    VS 查看引用的DLL/Nuget包源码时,无法看到注释
  • 原文地址:https://www.cnblogs.com/wally/p/3279827.html
Copyright © 2020-2023  润新知