Usaco Training Section 4.4 Pollutant Control

裸的最小割题。求最小割和删掉的边(使得删掉的边最少)

第一问很简单,用“最大流=最小割”定理,直接求最大流即可。第二问我们可以将每条边从大到小排序,删掉这条边,再跑最大流,如果删后最大流和原来最大流的差等于这条边,那么我们就选这条边,用sum加上这条边,直到sum=原来最大流就可结束。

注意:删掉的边要按递增序排。

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define inf 1<<29
#define mp make_pair
#define pii pair<int,int>
#define pb push_back
using namespace std;

inline int read(){
    int x=0;char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x;
}

int c[40][40],f[40][40],n,m,s,t,d[40];

inline bool bfs(){
    memset(d,0,sizeof(d));
    queue<int> q;
    q.push(s);d[s]=1;
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int v=1;v<=n;++v){
            if(c[u][v]>f[u][v]&&!d[v]){
                q.push(v);
                d[v]=d[u]+1;
                if(v==t) return 1;
            }
        }
    }
    return 0;
}

inline int dinic(int u,int flow){
    if(u==t) return flow;
    int rest=flow;
    for(int v=1;v<=n;++v){
        if(c[u][v]>f[u][v]&&d[v]==d[u]+1){
            int k=dinic(v,min(rest,c[u][v]-f[u][v]));
            if(!k) d[v]=0;
            f[u][v]+=k;
            f[v][u]-=k;
            rest-=k;
        }
    }
    return flow-rest;
}

inline int maxf(){
    int flow=0,maxflow=0;
    while(bfs()){
        while(flow=dinic(s,inf)) maxflow+=flow;
    }
    return maxflow;
}

struct node{
    int u,v,w,i;
}ed[2005];

inline bool cmp(node x,node y){
    return x.w>y.w;
}

int a[2005],ans;
int main()
{
    freopen("milk6.in","r",stdin);
    freopen("milk6.out","w",stdout);
    n=read(),m=read();
    s=1,t=n;
    for(int i=1;i<=m;++i){
        ed[i].u=read(),ed[i].v=read(),ed[i].w=read(),ed[i].i=i;
        c[ed[i].u][ed[i].v]+=ed[i].w;
    }
    int maxflow=maxf(),sum=0;
    printf("%d ",maxflow);
    sort(ed+1,ed+m+1,cmp);
    for(int i=1;i<=m;++i){
        memset(f,0,sizeof(f));
        c[ed[i].u][ed[i].v]-=ed[i].w;
        int s=maxf();
        if(s+ed[i].w==maxflow){
            a[++ans]=ed[i].i;
            sum+=ed[i].w;
            if(sum==maxflow) break;
        }
        c[ed[i].u][ed[i].v]+=ed[i].w;
    }
    printf("%d\n",ans);
    sort(a+1,a+ans+1);
    for(int i=1;i<=ans;++i) printf("%d\n",a[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36911709/article/details/82254150
今日推荐