POJ 3204

求一次最小割,dfs一遍,然后对每一个满流且是正向边的做一次检查,如果这条边的终点能够到达汇点,则说明可以拓宽这条边来改进网络。

View Code
  1 #include<cstdio>

  2 #include<cstring>

  3 #include<algorithm>

  4 using namespace std;

  5 const int N=1000,M=10000;

  6 const int inff=1<<29;

  7 int head[N],nc;

  8 struct edge

  9 {

 10     int x,y,next;

 11     int cap;

 12 } edge[M*3];

 13 void add(int x,int y,int cap)

 14 {

 15     edge[nc].x=x;

 16     edge[nc].y=y;

 17     edge[nc].cap=cap;

 18     edge[nc].next=head[x];

 19     head[x]=nc++;

 20     edge[nc].x=y;

 21     edge[nc].y=x;

 22     edge[nc].cap=0;

 23     edge[nc].next=head[y];

 24     head[y]=nc++;

 25 }

 26 int num[N],h[N],S,T,n;

 27 int findpath(int x,int flow)

 28 {

 29     if(x==T)

 30         return flow;

 31     int res=flow,pos=n-1;

 32     for(int i=head[x]; i!=-1; i=edge[i].next)

 33     {

 34         int y=edge[i].y;

 35         if(h[x]==h[y]+1&&edge[i].cap>0)

 36         {

 37             int tp=findpath(y,min(edge[i].cap,res));

 38             res-=tp;

 39             edge[i].cap-=tp;

 40             edge[i^1].cap+=tp;

 41             if(!res||h[S]==n)

 42                 return flow-res;

 43         }

 44         if(edge[i].cap>0&&h[y]<pos)

 45             pos=h[y];

 46     }

 47     if(res==flow)

 48     {

 49         num[h[x]]--;

 50         if(num[h[x]]==0)

 51         {

 52             h[S]=n;

 53             return flow-res;

 54         }

 55         h[x]=pos+1;

 56         num[h[x]]++;

 57     }

 58     return flow-res;

 59 }

 60 void Sap()

 61 {

 62     memset(h,0,sizeof(h));

 63     memset(num,0,sizeof(num));

 64     int ans=0;

 65     num[0]=n;

 66     while(h[S]!=n)

 67         ans+=findpath(S,inff);

 68 }

 69 bool vis[N];

 70 void dfs(int now)

 71 {

 72     vis[now]=true;

 73     for(int i=head[now];i!=-1;i=edge[i].next)

 74     {

 75         if(!vis[edge[i].y]&&edge[i].cap)

 76             dfs(edge[i].y);

 77     }

 78 }

 79 bool mark[N];

 80 bool check(int now)

 81 {

 82     mark[now]=true;

 83     if(now==T)

 84         return true;

 85     for(int i=head[now];i!=-1;i=edge[i].next)

 86     {

 87         if(!mark[edge[i].y]&&edge[i].cap&&check(edge[i].y))

 88                 return true;

 89     }

 90     return false;

 91 }

 92 int main()

 93 {

 94     int m;

 95     while(scanf("%d%d",&n,&m)!=EOF)

 96     {

 97         nc=0;

 98         memset(head,-1,sizeof(head));

 99         for(int i=0; i<m; i++)

100         {

101             int a,b,c;

102             scanf("%d%d%d",&a,&b,&c);

103             add(a,b,c);

104         }

105         S=0,T=n-1;

106         Sap();

107         memset(vis,false,sizeof(vis));

108         dfs(S);

109         int cnt=0;

110         for(int i=0;i<n;i++)

111         {

112             if(!vis[i])

113                 continue;

114             for(int j=head[i];j!=-1;j=edge[j].next)

115             {

116                 if(j&1)

117                     continue;

118                 int t=edge[j].y;

119                 if(!vis[t])

120                 {

121                     memset(mark,false,sizeof(mark));

122                     if(check(t))

123                         cnt++;

124                 }

125             }

126         }

127         printf("%d\n",cnt);

128     }

129     return 0;

130 }

你可能感兴趣的:(poj)