2019ICPC EC-FINAL E-Flow 贪心

2019ICPC EC-FINAL E-Flow

题意

给一个\(n\)个点\(m\)条边的图,图由若干条从\(1\)\(n\)的长度相同的独立路径构成,任意两条路径除了\(1\)号点和\(n\)号点没有公用的点,每条边有流量,每次操作可以使一条边的流量减一,另一条边的流量加一,问最少需要多少此操作可以使从\(1\)\(n\)的流量最大。

\(n\le 10^5,m \le 2\cdot 10^5\)

分析

因为每条路径的长度相同,若长度为\(x\),则最大流量为\(\frac{\sum flow}{x}\)

每条路径的流量的瓶颈是流量最小的那条边,将每条路径上的边权排序,一定是将流量大的边的转给流量小的边,

排序后,从小到大枚举所有路径上的第\(i\)条边作为瓶颈,若所有路径上第\(i\)条边的流量和小于最大流量,则通过后面的边可以转移过来和最大流量的差值,若已经大于等于最大流量了,后面的边一定都不是瓶颈了,算法结束。

Code

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
const int N=1e5+10;
const int inf=1e9+10;
int n,m;
int vis[N];
typedef pair<int,int> pii;
typedef long long ll;
vector<int>q;
vector<pii>g[N];
vector<vector<int> >v;
void dfs(int u){
    for(pii x:g[u]){
        q.push_back(x.se);
        dfs(x.fi);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    ll ans=0,sum=0;
    for(int i=1;i<=m;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        g[x].push_back(pii(y,z));
        sum+=z;
    }
    for(pii x:g[1]){
    	q.clear();
        q.push_back(x.se);
        dfs(x.fi);
        sort(q.begin(), q.end());
        v.push_back(q);
    }
    sum/=q.size();
    for(int i=0;i<q.size();i++){
    	ll tmp=0;
    	for(auto x:v){
    		tmp+=x[i];
    	}
    	if(tmp>=sum) break;
    	ans+=sum-tmp;
    }
    printf("%lld\n",ans);
    return 0;
}
posted @ 2020-10-06 20:09  xyq0220  阅读(219)  评论(0编辑  收藏  举报