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\n",ans);

139     }

140     return 0;

141 }
View Code

 

你可能感兴趣的:(poj)