网络流(Dinic && ISAP)

来源:互联网 发布:淘宝卖特产没证可以吗 编辑:程序博客网 时间:2024/06/04 19:00

放上一下模板的好。毕竟老忘。

Dinic: while(BFS()) ans+=DFS(S, ∞)

#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;#if 0Writers: Goes && G.S.M.Have falled in love#endifinline int read(){    char ch=getchar();int sum=0;    while(ch<'0'||ch>'9') ch=getchar();    while(ch>='0'&&ch<='9')        sum*=10,sum+=ch-'0',ch=getchar();    return sum;}const int N=1000010;const int INF=(1<<30);struct ss{    int to,nex,va;}edge[N<<1];int head[N],ecnt=1;int n,m,s,t;void add(int va,int y,int x){    edge[++ecnt]=(ss){y,head[x],va};    edge[++ecnt]=(ss){x,head[y],0};    head[x]=ecnt-1;head[y]=ecnt;}int level[N];bool BFS(){    memset(level,0,sizeof(level));    level[s]=1;queue<int>Q;Q.push(s);    while(!Q.empty()){        int pos=Q.front();Q.pop();        for(int i=head[pos];i;i=edge[i].nex)        if(edge[i].va&&!level[edge[i].to]){            level[edge[i].to]=level[pos]+1;            Q.push(edge[i].to);        }    }return level[t];}int DFS(int pos,int mflow){    if(!mflow||pos==t)return mflow;int ret=0;    for(int i=head[pos];i;i=edge[i].nex)    if(edge[i].va&&level[edge[i].to]==level[pos]+1)    {        int temp=DFS(edge[i].to,min(mflow,edge[i].va));        ret+=temp;mflow-=temp;edge[i].va-=temp;        edge[i^1].va-=temp;    }return ret;}inline int Dinic(){    int ret=0;while(BFS())ret+=DFS(s,INF);    return ret;}int main(){    n=read(),m=read(),s=read(),t=read();    for(int i=1;i<=m;i++)        add(read(),read(),read());    printf("%d",Dinic());return 0;}

ISAP:一次BFS定级,后续按最近点级数修改。
优化关键:gap优化,cur数组的优化
思路:能往下流就往下流,不能流了回溯修改。

(60ms……比dinic的300ms 靠谱多了……emmmm…..)

#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;#if 0Writers: Goes && G.S.M.Have falled in love#endifconst int N=100007;const int INF=(1<<30);inline int read(){    char ch=getchar();int sum=0;    while(ch<'0'||ch>'9') ch=getchar();    while(ch>='0'&&ch<='9')        sum*=10,sum+=ch-'0',ch=getchar();    return sum;}int n,m,S,T;struct ss{    int to,nex,va;}edge[N<<1];int head[N],ecnt=1;void add(int va,int y,int x){    edge[++ecnt]=(ss){y,head[x],va};    edge[++ecnt]=(ss){x,head[y],0};    head[x]=ecnt-1;head[y]=ecnt;}int dis[N],num[N],cur[N],fa[N];void BFS(){    for(int i=1;i<=n;i++) dis[i]=N;    queue<int>Q;Q.push(T);dis[T]=0;    while(!Q.empty()){        int pos=Q.front();Q.pop();        for(int i=head[pos];i;i=edge[i].nex)        if(edge[i^1].va&&dis[edge[i].to]>dis[pos]+1)        {            dis[edge[i].to]=dis[pos]+1;            Q.push(edge[i].to);        }    }return ;}int out(){    int pos=T,f=INF;    while(pos!=S)pos=fa[pos],f=min(f,edge[cur[pos]].va);    pos=T;    while(pos!=S)pos=fa[pos],        edge[cur[pos]].va-=f,        edge[cur[pos]^1].va+=f;    return f;}inline int gswork(){    BFS();int pos=S,flow=0;    for(int i=1;i<=n;i++)        num[dis[i]]++,cur[i]=head[i];    while(dis[S]<n){        if(pos==T)flow+=out(),pos=S;        bool done = false;        for(int i=cur[pos];i;i=edge[i].nex)        if(edge[i].va&&dis[pos]==dis[edge[i].to]+1)        {            fa[edge[i].to]=pos;cur[pos]=i;            pos=edge[i].to;done=true;i=0;        }        if(!done){            int minx=n;            for(int i=head[pos];i;i=edge[i].nex)            if(edge[i].va) minx=min(minx,dis[edge[i].to]);            if(--num[dis[pos]]==0)break;            num[dis[pos]=minx+1]++;cur[pos]=head[pos];            if(pos!=S)pos=fa[pos];        }    }return flow;}inline void gsin(){    n=read();m=read();S=read(),T=read();    for(int i=1;i<=m;i++)        add(read(),read(),read());}int main(){gsin();printf("%d",gswork());return 0;}
原创粉丝点击