BZOJ-2561: 最小生成树(最小割)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2561

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define maxn  20010
#define maxm  400100
int e[maxn],u[maxm],ne[maxm],v[maxm],l[maxm],n,m,tt=1;
int s,t,L;
bool been[maxn];
void add(int x,int y,int z){
      ne[++tt]=e[x],e[x]=tt,v[tt]=y,l[tt]=z;
}
int ch[maxn];
bool bfs(){
    memset(ch,-1,sizeof(ch));
    queue<int> jj;
    jj.push(s);
    ch[s]=0;
    while(!jj.empty()){
       int x=jj.front();
       jj.pop();
       for(int i=e[x];i;i=ne[i])if(u[i]&&ch[v[i]]==-1){
            ch[v[i]]=ch[x]+1;
            jj.push(v[i]);
        }    
    }    
    return ch[t]!=-1;
}
int zeng(int no,int mm){
    if(no==t)return mm;
    int r=mm;
    for(int i=e[no];i&&r;i=ne[i])if(u[i]&&ch[v[i]]==ch[no]+1){
        int k=zeng(v[i],min(u[i],r));
        r-=k,u[i]-=k,u[i^1]+=k;
    }
    if(r==mm)return ch[no]=-1,0;
    return mm-r;
}
int dinic(){
  int tt,r=0;
  while(bfs())while(tt=zeng(s,0x3fffffff))r+=tt;
  return r;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
      int a,b,c;
      scanf("%d%d%d",&a,&b,&c);
      add(a,b,c);
      add(b,a,c);    
    }
    scanf("%d%d%d",&s,&t,&L);
    for(int i=1;i<=tt;i++)if(l[i]<L)u[i]=1;
    else u[i]=0;
    int ans=dinic();
    for(int i=1;i<=tt;i++)if(l[i]>L)u[i]=1;
    else u[i]=0;
    ans+=dinic();
    cout<<ans;
}

 

两遍最小割

posted @ 2014-04-11 16:46  wangyucheng  阅读(219)  评论(0编辑  收藏  举报