LINK
题意:
给你一张图,这个图保证1到n的路径长度相同并且不相交,每条边会有个流量,每次操作可以使得一条的流量-1,一条边的流量+1,问最少操作多少次可以满足最大流量
思路:
这个图大概长成这样。
考场上并没有发现很好的性质,只发现了每条路径的容量取决于
m
i
n
(
∑
c
)
min(\sum c)
min(∑c),然后想着该怎么把大的容量转移给小的,然后。。就做不出来了。后来看了正解,正解是把每条路径按照容量排序,由于我们可以先知道答案的流量,然而如果要流
a
n
s
ans
ans的流量,那么一定要满足每条边都要满足至少
a
n
s
ans
ans,假设有
k
k
k条路径,长度为
l
e
n
len
len,我们从头往后操作,如果当前的
s
u
m
<
a
n
s
sum<ans
sum<ans,那么后面一定有大的容量可以分配给它,对于答案的贡献是
a
n
s
−
s
u
m
ans-sum
ans−sum否则直接break就行了。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=400010;
#define int long long
int h[N],ne[N],w[N],idx,e[N];
void add(int a,int b,int c){
e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
//vector<int>v
//void dfs()
vector<int>path[N];
signed main(){
int n,m;
int dd=0;
cin>>n>>m;
memset(h,-1,sizeof h);
int sum=0;
while(m--){
int a,b,c;
cin>>a>>b>>c;
sum+=c;
add(a,b,c);
add(b,a,c);
}
int ans;
for(int i=h[1];~i;i=ne[i])
{
++dd;
int x=e[i];
path[dd].push_back(w[i]);
int ww;
int pre=1;
while(true)
{
// cout<<x<<endl;
if(x==n)
break;
for(int d=h[x];~d;d=ne[d])
{
if(e[d]==pre) continue;
int k=e[d];
path[dd].push_back(w[d]);
pre=x;
x=k;
break;
}
}
sort(path[dd].begin(),path[dd].end());
ans=sum/path[dd].size();
}
// cout<<ans<<endl;
int res=0;
for(int i=0;i<path[dd].size();i++){
int xsum=0;
for(int j=1;j<=dd;j++)
xsum+=path[j][i];
if(xsum>=ans)
break;
else;
res+=ans-xsum;
}
cout<<res;
return 0;
}