Ford-Fulkson用EK实现:483ms
#include <cstdio>
#include <cstring>
#define min(x,y) (x>y?y:x)
int pre[105],q[105];
int F[105][105];
int n,nc,np,m,s,t,all;
int MaxFlow(int s, int t){
    int ans=0;
    while(1){
        memset(pre,0,sizeof(pre));
        int head=0,tail=0;
        q[++tail]=s;
        while(head<tail&&pre[t]==0){
            int cur=q[++head];
            for(int i=1; i<=n; i++)
            if(F[cur][i]>0&&pre[i]==0){
                pre[i]=cur;
                q[++tail]=i;
            }
        }
        if(pre[t]==0) break;
        int minF=100000000;
        for(int i=t; i!=s; i=pre[i])
            minF=min(minF,F[pre[i]][i]);
        for(int i=t; i!=s; i=pre[i])
        {
            F[pre[i]][i]-=minF;
            F[i][pre[i]]+=minF;
        }
        ans+=minF;
    }
    return ans;
}
int main()
{
    int x,y,z;
    while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF){
        all=0;
        memset(F,0,sizeof(F));
        s=n+1;
        t=n+2;
        n=n+2;
        for(int i=0; i<m; i++){
            while(getchar()!='(') ;
            scanf("%d,%d)%d",&x,&y,&z);
            F[x+1][y+1]=z;
        }
        for(int i=0; i<np; i++){
            while(getchar()!='(') ;
            scanf("%d)%d",&x,&z);
            F[s][x+1]=z;
        }
        for(int i=0; i<nc; i++){
            while(getchar()!='(') ;
            scanf("%d)%d",&x,&z);
            F[x+1][t]=z;
        }
        printf("%d\n",MaxFlow(s,t));
    }
    return 0;
}
View Code

Dinic用DFS实现:360ms

#include <cstdio>
#include <cstring>
#define min(x,y) ((x)>(y)?(y):(x))
#define N 105
#define M 10005
int n,np,nc,m,all,s,t;
int d[N],be[N];
struct Edge{
    int x,y,c,next;
}e[M*2];
void add(int x, int y, int z)//需保证相反边第一个为偶数
{
    e[all].x=x; e[all].y=y; e[all].c=z;
    e[all].next=be[x];
    be[x]=all;
    all++;
    e[all].x=y; e[all].y=x; e[all].c=0;
    e[all].next=be[y];
    be[y]=all;
    all++;
}
bool BFS(int s, int t)
{
    memset(d,-1,sizeof(d));
    int head=0,tail=0,q[N];
    q[++tail]=s;
    d[s]=0;
    while(head<tail){
        int cur=q[++head];
        for(int i=be[cur]; i!=-1; i=e[i].next)
        if(e[i].c>0 && d[e[i].y]==-1){
            d[e[i].y]=d[cur]+1;
            q[++tail]=e[i].y;
        }
    }
    return d[t]!=-1;
}
int DFS(int cur, int minc)
{
    if(cur==t) return minc;//表示路径上该点前方最小容量
    int ans=0,tmp;//ans表示该点要增大的流
    for(int i=be[cur]; i!=-1; i=e[i].next)
    if(e[i].c>0 && d[e[i].y]==d[cur]+1 && (tmp=DFS(e[i].y,min(minc-ans,e[i].c))))//多路增广很快 因为不用返回到s 容易证明能保证minc>0
    {
        e[i].c-=tmp;
        e[i^1].c+=tmp;
        ans+=tmp;
    }
    if(ans==0) d[cur]=-1;//关键的一句话 否则超时 用于多路增广 
    return ans;
}
int Dinic(int s, int t)
{
    int ans=0,tmp;
    while(BFS(s,t)){
        while(tmp=DFS(s,1000000000))
            ans+=tmp;
    }
    return ans;
}
int main()
{
    int x,y,z;
    while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF){
        all=0;
        memset(be,-1,sizeof(be));
        s=n;
        t=n+1;
        n=n+2;
        for(int i=0; i<m; i++){
            while(getchar()!='(') ;
            scanf("%d,%d)%d",&x,&y,&z);
            add(x,y,z);
        }
        for(int i=0; i<np; i++){
            while(getchar()!='(') ;
            scanf("%d)%d",&x,&z);
            add(s,x,z);
        }
        for(int i=0; i<nc; i++){
            while(getchar()!='(') ;
            scanf("%d)%d",&x,&z);
            add(x,t,z);
        }
        printf("%d\n",Dinic(s,t));
    }
    return 0;
}
View Code

Dinic用栈模拟递归实现:63ms

#include <cstdio>
#include <cstring>
#define min(x,y) ((x)>(y)?(y):(x))
#define N 105
#define M 10005
int n,np,nc,m,all,s,t;
int d[N],be[N];
struct Edge{
    int x,y,c,next;
}e[M*2];
void add(int x, int y, int z)//需保证相反边第一个为偶数
{
    e[all].x=x; e[all].y=y; e[all].c=z;
    e[all].next=be[x];
    be[x]=all;
    all++;
    e[all].x=y; e[all].y=x; e[all].c=0;
    e[all].next=be[y];
    be[y]=all;
    all++;
}
bool BFS(int s, int t)
{
    memset(d,-1,sizeof(d));
    int head=0,tail=0,q[N];
    q[++tail]=s;
    d[s]=0;
    while(head<tail){
        int cur=q[++head];
        for(int i=be[cur]; i!=-1; i=e[i].next)
        if(e[i].c>0 && d[e[i].y]==-1){
            d[e[i].y]=d[cur]+1;
            q[++tail]=e[i].y;
        }
    }
    return d[t]!=-1;
}
int Dinic(int s, int t)//防止爆栈 用stack模拟递归
{
    int ans=0;
    int stack[N],top;
    int begin[N];
    while(BFS(s,t))
    {
        memcpy(begin,be,sizeof(be));
        int cur=s;
        top=0;//dfs开始 清空栈
        while(1)
        {
            if(cur==t){
                int minc=1000000000,mini;
                for(int i=0; i<top; i++)
                if(minc>e[stack[i]].c)
                {
                    minc=e[stack[i]].c;
                    mini=i;//以便之后回到这继续增广
                }
                for(int i=0; i<top; i++)
                {
                    e[stack[i]].c-=minc;
                    e[stack[i]^1].c+=minc;//第一个二进制取反 即取相反边
                }
                ans+=minc;
                top=mini;
                cur=e[stack[mini]].x;
            }
            for(int i=begin[cur]; i!=-1; begin[cur]=i=e[begin[cur]].next)
                if(e[i].c>0 && d[e[i].y]==d[e[i].x]+1) break;
            if(begin[cur]!=-1){
                stack[top++]=begin[cur];
                cur=e[begin[cur]].y;
            }else{
                if(top==0) break;
                d[cur]=-1;//当前节点不在增广路中 删除
                cur=e[stack[--top]].x;//回溯
            }
        }
    }
    return ans;
}
int main()
{
    int x,y,z;
    while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF){
        all=0;
        memset(be,-1,sizeof(be));
        s=n;
        t=n+1;
        n=n+2;
        for(int i=0; i<m; i++){
            while(getchar()!='(') ;
            scanf("%d,%d)%d",&x,&y,&z);
            add(x,y,z);
        }
        for(int i=0; i<np; i++){
            while(getchar()!='(') ;
            scanf("%d)%d",&x,&z);
            add(s,x,z);
        }
        for(int i=0; i<nc; i++){
            while(getchar()!='(') ;
            scanf("%d)%d",&x,&z);
            add(x,t,z);
        }
        printf("%d\n",Dinic(s,t));
    }
    return 0;
}
View Code

相关文章:

  • 2022-12-23
  • 2021-11-07
  • 2021-10-19
  • 2021-05-08
  • 2021-12-23
  • 2021-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-08-25
  • 2022-01-04
  • 2022-01-13
  • 2021-09-13
相关资源
相似解决方案