[最小割]luogu P1344 [USACO4.4]追查坏牛奶Pollutant Control

题面

https://www.luogu.com.cn/problem/P1344

分析

很简单的网络流,重点在于如何维护最小割边数最少。

考虑对每条边的流量在其基础上乘以一个大于总边数的值,再+1

那么新图最大流/总边数即为原图最小割,%总边数即为最小割最少边数。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll;
const ll Inf=3e9+10;
const int N=1e3+10;
struct Graph {
    ll c;
    int v,nx;
}g[2*N];
int cnt=1,list[35],d[35];
int n,m,s,t;
ll ans;

void Add(int u,int v,ll c) {g[++cnt]=(Graph){c,v,list[u]};list[u]=cnt;}

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

ll MF(int u,ll maxf) {
    ll out=0,f;
    if (!maxf||u==t) return maxf;
    for (int i=list[u];i;i=g[i].nx)
        if (d[u]+1==d[g[i].v]) {
            f=MF(g[i].v,min(maxf-out,g[i].c));
            out+=f;
            g[i].c-=f;g[i^1].c+=f;
            if (out==maxf) return out;
        }
    return out;
}

void Dinic() {
    while (BFS()) ans+=MF(s,Inf);
}

int main() {
    scanf("%d%d",&n,&m);s=1;t=n;
    for (int i=1,u,v,c;i<=m;i++) scanf("%d%d%d",&u,&v,&c),Add(u,v,1ll*c*(m+1)+1),Add(v,u,0);
    Dinic();
    printf("%lld %lld",ans/(m+1),ans%(m+1));
}
View Code

 

posted @ 2020-10-21 21:27  Vagari  阅读(92)  评论(0编辑  收藏  举报