One of Pang’s research interests is the maximum flow problem.
A directed graph G with n vertices is universe if the following condition is satisfied:
G is the union of k vertex-independent simple paths from vertex 1 to vertex n of the same length.
A set of paths is vertex-independent if they do not have any internal vertex in common.
A vertex in a path is called internal if it is not an endpoint of that path.
A path is simple if its vertices are distinct.
Let G be a universe graph with n vertices and m edges. Each edge has a non-negative integral capacity. You are allowed to perform the following operation any (including 0) times to make the maximum flow from vertex 1 to vertex n as large as possible:
Let e be an edge with positive capacity. Reduce the capacity of e by 1 and increase the capacity of another edge by 1.
Pang wants to know what is the minimum number of operations to achieve it?
Input
The first line contains two integers n and m (2≤n≤100000,1≤m≤200000).
Each of the next m lines contains three integers x,y and z, denoting an edge from x to y with capacity z (1≤x,y≤n, 0≤z≤1000000000).
It’s guaranteed that the input is a universe graph without multiple edges and self-loops.
Output
Output a single integer — the minimum number of operations.
Examples
inputCopy
4 3
1 2 1
2 3 2
3 4 3
outputCopy
1
inputCopy
4 4
1 2 1
1 3 1
2 4 2
3 4 2
outputCopy
1
因为没条边的数量是一定的,所以总共最大流一定是一定的。
我们对每一条路径按照流量从小到大排序。
对于每一个的第一条边,如果总和小于flow,那么必然从后面大的边拿过来,否则直接break即可。
从后面拿很明显的满足贪心的。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10,M=N<<1;
int n,m,flow,res,cnt;
int head[N],nex[M],to[M],w[M],tot;
vector<int> v[N];
inline void add(int a,int b,int c){
to[++tot]=b; nex[tot]=head[a]; w[tot]=c; head[a]=tot;
}
void dfs(int x){
if(x==n) return ;
for(int i=head[x];i;i=nex[i]){
v[cnt].push_back(w[i]); dfs(to[i]);
}
}
signed main(){
ios::sync_with_stdio(false); cin.tie(nullptr);
cin>>n>>m;
for(int i=1,a,b,c;i<=m;i++) cin>>a>>b>>c,add(a,b,c),flow+=c;
for(int i=head[1];i;i=nex[i]){
v[++cnt].push_back(w[i]); dfs(to[i]);
sort(v[cnt].begin(),v[cnt].end());
}
flow/=v[1].size();
for(int i=0,s;i<v[1].size();i++){
s=0;
for(int j=1;j<=cnt;j++) s+=v[j][i];
if(s>=flow) break; res+=flow-s;
}
cout<<res;
return 0;
}