最小费用最大流

矩阵形式:


#include

#define MAXN 0x3f3f3f3f

using namespace std;

const int maxn=500;
int n,s=1,t;
int c[maxn][maxn],g[maxn][maxn],d[maxn];
int pre[maxn];
bool vis[maxn];
int p=0;

void augment(){
    int i=t;
    int a=MAXN;
    while(i>s){
        if(c[pre[i]][i]s){
        c[pre[i]][i]-=a;
        c[i][pre[i]]+=a;
        i=pre[i];
    }
}

bool spfa(){
    memset(vis,0,sizeof(vis));
    memset(pre,0,sizeof(pre));
    queue q;
    for(int i=1;i<=t;i++){
        d[i]=MAXN;
    }
    q.push(s);
    vis[s]=1;
    d[s]=0;
    while(!q.empty()){
        int x=q.front();
        q.pop();
        vis[x]=0;
        for(int i=1;i<=t;i++){
            if(d[i]>d[x]+g[x][i]&&c[x][i]>0){
                d[i]=d[x]+g[x][i];
                pre[i]=x;
                if(!vis[i]){
                    vis[i]=1;
                    q.push(i);
                }
            }
        }
    }
    if(d[t]!=(int)MAXN){
        return 1;
    }
    return 0;
}

int main()
{
    (ios::sync_with_stdio(false),cin.tie(0));
    cin>>n;
    t=2*n+2;
    for(int i=1;i<=n;i++){
        int sum=0;
        for(int j=1;j<=n;j++){
            c[i+1][1+n+j]=1;
            cin>>g[1+i][1+n+j];
            sum+=g[1+i][1+n+j];
        }
        for(int j=1;j<=n;j++){
            g[1+i][1+n+j]=sum-g[1+i][1+n+j];
            g[1+n+j][1+i]=-g[1+i][1+n+j];
        }
    }
    for(int i=1;i<=n;i++){
        c[1][1+i]=1;
        c[1+n+i][t]=1;
    }
    while(spfa()){
        augment();
        p+=d[t];
    }
    cout<

邻接表形式。

#include

using namespace std;

const int MAXN=110;

const int MAXM=5010;

struct node{
    int to;
    int next;
    int c;      //容量
    int f;      //费用
}edge[MAXN*10];

int head[MAXN];
int n,s,t;
int dis[MAXN],load[MAXN],p[MAXN];
//dis: 最短路中的距离数组。
//load:记录每个点的前驱边。
//p:记录每个点的前驱边。
int eid;

void init(){
    memset(head,-1,sizeof(head));
    eid=0;
}

void insert(int u,int v,int w,int f){
    edge[eid].to=v;
    edge[eid].next=head[u];
    edge[eid].c=w;
    edge[eid].f=f;
    head[u]=eid++;
}

void addedge(int u,int v,int w,int f){
    insert(u,v,w,f);//正向弧容量为w,费用为f
    insert(v,u,0,-f);//反向弧容量为0,费用为-f
}

bool flag[MAXN];

bool SPFA(){

    memset(flag,0,sizeof(0));
    memset(load,-1,sizeof(load));
    memset(p,-1,sizeof(p));
    for(int i=1;i<=t;i++)
        dis[i]=INT_MAX;
    queue q;
    q.push(s);
    dis[s]=0;
    flag[s]=1;
    while(!q.empty()){
        int e=q.front();
        flag[e]=0;
        q.pop();
        for(int i=head[e];i!=-1;i=edge[i].next){
            if(edge[i].c){
                int ne=edge[i].to;
                if(dis[ne]>dis[e]+edge[i].f){
                    dis[ne]=dis[e]+edge[i].f;
                    p[ne]=e;
                    load[ne]=i;
                    if(!flag[ne]){
                        flag[ne]=true;
                        q.push(ne);
                    }
                }
            }
        }
    }
    if(dis[t]==INT_MAX) return false;
    return true;
}

int Min_cost_Flow(){
     int u,mn;
     int ans_flow=0,ans_cost=0;
     while(SPFA()){
        u=t;
        mn=INT_MAX;
        while(p[u]!=-1){
            mn=min(edge[load[u]].c,mn);
            u=p[u];
        }
        u=t;
        while(p[u]!=-1){
            edge[load[u]].c-=mn;
            edge[load[u]^1].c+=mn;
            u=p[u];
        }
        ans_cost+=dis[t]*mn;
        ans_flow+=mn;
     }
     return ans_cost;
}

int main(){
    init();
    int m;
    cin>>n>>m>>s>>t;
    while(m--){
        int u,v,w,f;
        cin>>u>>v>>w>>f;
        addedge(u,v,w,f);
    }
    cout<

 

你可能感兴趣的:(模板,图论)