beloved_ACM

SB,NB,都是一个B.
posts - 29, comments - 2, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

题目意思是要求边有扩容之后能使流量加大,问这样的边有几条,这里要注意的是,最小割不一定就是这种边,但是这种边就一定是割了,因为假设可能有一条增光路上有和最小割相同容量的边,那么扩容了最小割也没用,所以一次DFS正向反向都不行,必须两次DFS。正的来一次,反向图从汇点来一次,标记1,2然后连接1和2的那条边就是可扩容边。假设x-.y是可扩容边,那么必定有,s->x和y->t存在。

【题目大意】

给出一张传输流量图,求给哪些边添加容量,可以增大最大流。
【解题思路】

实际上就是求割边,但这个割边必需是一头能被源到达,另一头能被汇到达。

【Code】

#include 
<algorithm>
#include 
<iostream>
#include 
<cstdlib>
#include 
<cstring>
#include 
<cstdio>
#include 
<cmath>
using namespace std;

#define MAXN 510
#define MAXM 10010
#define inf 1000000000


struct Edge
{
 
int to, from, flow, cap;
 
int next, pair;  //pair表示跟它是一对的另一边
}
;

int n, m;
int source, sink;        //源点和汇点
Edge edge[MAXM];
int cnt, pn[MAXN];

void addedge(int from, int to, int cap)   //一次增加两条边
{
 edge[cnt].from 
= from;
 edge[cnt].to 
= to;
 edge[cnt].next 
= pn[from];
 edge[cnt].cap 
= cap;
 edge[cnt].flow 
= 0;
 edge[cnt].pair 
= cnt + 1;
 pn[from] 
= cnt++;

 
//增加另一条边
 edge[cnt].from = to;
 edge[cnt].to 
= from;
 edge[cnt].next 
= pn[to];
 edge[cnt].cap 
= 0;
 edge[cnt].flow 
= 0;
 edge[cnt].pair 
= cnt - 1;
 pn[to] 
= cnt++
}


int numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN];


int ISAP()
{   
    
int cur_flow,max_flow,u,tmp,neck,i;
    memset(dist,
0,sizeof(dist));
    memset(numb,
0,sizeof(numb));   //初始化为0,不需要反向bfs了
    for(i = 1 ; i <= n ; ++i)
        curedge[i] 
= pn[i];
    numb[n] 
= n;
    max_flow 
= 0;
    u 
= source;
    
while(dist[source] < n)
 
{
        
if(u == sink)
  
{
            cur_flow 
= inf + 1;   //!!!!注意这里要大于inf
            for(i = source; i != sink; i = edge[curedge[i]].to)
                
if(cur_flow > edge[curedge[i]].cap)
    
{
                    neck 
= i;
                    cur_flow 
= edge[curedge[i]].cap;
                }

            
for(i = source; i != sink; i = edge[curedge[i]].to)
            
{
                tmp 
= curedge[i];
                edge[tmp].cap 
-= cur_flow;
                edge[tmp].flow 
+= cur_flow;
                tmp 
= edge[tmp].pair;
                edge[tmp].cap 
+= cur_flow;
                edge[tmp].flow 
-= cur_flow;
            }

            max_flow 
+= cur_flow;
            u 
= neck;
        }

        
for(i = curedge[u]; i != -1; i = edge[i].next)
            
if(edge[i].cap > 0 && dist[u] == dist[edge[i].to]+1)
                
break;
        
if(i != -1)
  
{
            curedge[u] 
= i;
            pre[edge[i].to] 
= u;
            u 
= edge[i].to;
        }

  
else
  
{
            
if(0 == --numb[dist[u]])
    
break;
            curedge[u] 
= pn[u];
            
for(tmp = n,i = pn[u]; i != -1; i = edge[i].next)
                
if(edge[i].cap > 0)
                    tmp 
= tmp<dist[edge[i].to]?tmp:dist[edge[i].to];
            dist[u] 
= tmp + 1;
            
++numb[dist[u]];
            
if(u != source)
    u 
= pre[u];
        }

    }

    
return max_flow;
}


int mat[MAXN][MAXN];
bool vs[MAXN],vt[MAXN];

void dfs(int k, bool v[MAXN])     //求从k出发可以到达的所有顶点
{
 
int i;
    v[k] 
= 1;
    
for (i = 1; i <= n; i++)
      
if (!v[i] && mat[k][i])
    dfs(i, v);
}


void work()
{
 
int i;
 memset(mat,
0,sizeof(mat));

 
for (i = 1; i < cnt; i += 2)
 
{
  
if (edge[i].cap)  //非满流边
  {
   mat[edge[i].from][edge[i].to] 
= 1;
  }

 }

    memset(vs,
0,sizeof(vs));
    dfs(source, vs);                        
//从0开始搜索   
   
    memset(mat,
0,sizeof(mat));
    
for (i = 1; i < cnt; i += 2)
 
{
  
if (edge[i].cap)
  
{
   mat[edge[i].to][edge[i].from] 
= 1;
  }

 }

    memset(vt,
0,sizeof(vt));
    dfs(sink,vt);                      
//从n-1开始搜索  

 
int  ans = 0;
 
for (i = 1; i < cnt; i += 2)
 
{
  
if (!edge[i].cap && vs[edge[i].from] && vt[edge[i].to])  
   ans
++;  
 }

 printf(
"%d\n",ans); 
}



int main()
{   
    
int u, v, w;
 
//   freopen("in.txt","r",stdin);
    scanf("%d %d",&n,&m);
 memset(pn,
0xff,sizeof(pn));
 cnt 
= 1;
 
while (m--)
 
{
  scanf(
"%d %d %d",&u,&v,&w);
  u
++;
  v
++;
  addedge(u,v,w);
 }

    source 
= 1;
 sink 
= n;
 u 
= ISAP();
 work();    
    
return 0;   
}
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理