P1344 [USACO4.4] 追查坏牛奶 Pollutant Control - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
利用Dinic()算法求最小割。
关于最小分割边数,看到一优质题解做法非常好(题解 P1344 【[USACO4.4]追查坏牛奶Pollutant Control】 - 浅色调 的博客 - 洛谷博客 (luogu.com.cn))做法:加边时边权设为c*cnt+1.,最小割为ans/cnt,最小边数为ans%cnt。解释:
最小割的每一条边地容量的和即是最小割的值,即c1*cnt+1+c2*cnt+1+c3*cnt+1……=ans*cnt+k
则只需保证cnt>k,即让cnt大于边数m即可。
#include<iostream>
#include<vector>
#include<cstring>
#include<string>
#include<queue>
using namespace std;
const int M = 50500, N = 50050;
typedef long long ll;
struct node { ll v, c, ne; }edge[M];
int h[N],idx=1;//从2,3开始配对
int d[N], cur[N];
int n,m,s, t;
void add(int a,int b,long long c)
{
edge[++idx] = { b,c,h[a] };
h[a] = idx;
}
bool bfs()//对点分层,找增广路
{
memset(d, 0, sizeof(d));
queue<int> q;
q.push(s);
d[s] = 1;
while (q.size())
{
int u = q.front(); q.pop();
for (int i = h[u]; i; i = edge[i].ne)
{
int v = edge[i].v;
if (d[v] == 0 && edge[i].c)
{
d[v] = d[u] + 1;
q.push(v);
if (v == t)
return 1;
}
}
}
return 0;
}
ll dfs(int u,ll mf)
{
if (u == t) return mf;
long long sum = 0;
for (int i = cur[u]; i; i = edge[i].ne)
{
cur[u] = i;
int v = edge[i].v;
if (d[v] == d[u] + 1&&edge[i].c)
{
long long f = dfs(v, min(mf, edge[i].c));
edge[i].c -= f;
edge[i ^ 1].c += f;
mf -= f;
sum += f;
if (mf == 0) break;
}
}
if (sum == 0) d[u] = 0;
return sum;
}
ll Dinic()
{
ll flow = 0;
while (bfs())
{
memcpy(cur, h, sizeof(h));
flow += dfs(s, 1e9);
}
return flow;
}
int vis[N];
void mincut(int u)//划分代码,没用到
{
vis[u] = 1;
for (int i = h[u]; i; i = edge[i].ne)
{
int v = edge[i].v;
if(!vis[v]&&edge[i].c)
mincut(v);
}
}
int main()
{
cin >> n >> m;
s = 1; t = n;
int a[N], b[N],c[N];
memset(cur, 0, sizeof(cur));
int cnt = 1005;
for (int i = 1; i <= m; i++)
{
cin >> a[i] >> b[i] >> c[i];
add(a[i], b[i], c[i]*cnt+1);
add(b[i], a[i], 0);
}
long long ans = Dinic();
cout<<ans/cnt<<" "<<ans%cnt;
}