poj 3469 最小割模板sap+gap+弧优化

/*以核心1为源点,以核心2为汇点建图,跑一遍最大流*/
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 21000
#define inf 999999999
struct node {
int u,v,w,next;
}bian[N*40];
int head[N],cur[N],gap[N],stac[N],top,n,sink,source,yong,start,dis[N];
void init() {
memset(head,-1,sizeof(head));
  top=0;yong=0;
}
void addedge(int u,int v,int w){
bian[yong].u=u;
bian[yong].v=v;
bian[yong].w=w;
bian[yong].next=head[u];
head[u]=yong++;
}
void bfs() {
queue<int>q;
memset(dis,-1,sizeof(dis));
q.push(sink);
dis[sink]=0;
while(!q.empty()) {
    int c=q.front();
    int i;
    q.pop();
    for(i=head[c];i!=-1;i=bian[i].next) {
        int v=bian[i].v;
        if(dis[v]==-1) {
            dis[v]=dis[c]+1;
            q.push(v);
        }
    }
}
}
int ISAP() {
int i,sum=0,k;
bfs();
memset(gap,0,sizeof(gap));
for(i=1;i<=n;i++) {
    gap[dis[i]]++;
    cur[i]=head[i];
}
    k=source;
while(dis[source]<n) {
      if(k==sink) {
            int mi=inf,tep;
        for(i=0;i<top;i++){
            int e=stac[i];
            if(mi>bian[e].w) {
                mi=bian[e].w;
                tep=i;
            }
        }
        for(i=0;i<top;i++) {
            int e=stac[i];
            bian[e].w-=mi;
            bian[e^1].w+=mi;
        }
        sum+=mi;
        top=tep;
        k=bian[stac[top]].u;
      }
      for(i=cur[k];i!=-1;i=bian[i].next) {
        int v=bian[i].v;
            if(bian[i].w&&dis[k]==dis[v]+1) {
                cur[k]=i;
                k=v;
                stac[top++]=i;
            break;
            }
      }
      if(i==-1) {
        int m=n,i;
        for(i=head[k];i!=-1;i=bian[i].next) {
            int v=bian[i].v;
            if(m>dis[v]&&bian[i].w) {
                m=dis[v];
                cur[k]=i;
            }
        }
        if(--gap[dis[k]]==0)break;
        gap[dis[k]=m+1]++;
        if(k!=source)
            k=bian[stac[--top]].u;
      }
}
return sum;
}
int main() {
    int i,a,b,c,m;
    while(scanf("%d%d",&n,&m)!=EOF) {
        source=n+1;
        sink=n+2;
        init();
    for(i=1;i<=n;i++) {
        scanf("%d%d",&a,&b);
        addedge(source,i,a);
        addedge(i,source,0);
        addedge(i,sink,b);
        addedge(sink,i,0);
    }
    while(m--) {
        scanf("%d%d%d",&a,&b,&c);
        addedge(a,b,c);
        addedge(b,a,c);
    }
    n+=2;
    printf("%d\n",ISAP());
    }
return 0;
}

posted @ 2014-07-22 09:47  HYDhyd  阅读(134)  评论(0编辑  收藏  举报