1. 程式人生 > 實用技巧 >2019EC-FINAL E題 Flow(貪心)

2019EC-FINAL E題 Flow(貪心)

這題的圖非常特殊,首先他沒有交點,其次他每條路徑的長度都是相等的,也就是每一條邊都是對應的。

根據常規的貪心思路,因為他的最大流是全部路徑中的流量和,並且你將一個邊-1,必有另一個邊+1,最大流的答案就是總容量/路徑上的邊數

那麼其實可以想出做法了,我們已經知道的最大流是多少,所以我們將路徑按權值排序,對應路徑上的容量全部相加,因為每條路都會收到容量小的邊的控制,所以一定要貫通這些邊,使得他們的和大於最大流。

只需要判斷最大流是否大於當前容量和即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+10; int h[N],ne[N],e[N],w[N],idx; vector<int> g[N]; int n,m,cnt; void add(int a,int b,int c){ e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++; } void dfs(int u,int fa){ if(u==n) return ; int i; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa)
continue; g[cnt].push_back(w[i]); dfs(j,u); } } int main(){ ios::sync_with_stdio(false); memset(h,-1,sizeof h); int i; cin>>n>>m; ll flow=0; for(i=1;i<=m;i++){ int x,y,z; cin>>x>>y>>z; add(x,y,z); flow
+=z; } for(i=h[1];i!=-1;i=ne[i]){ int j=e[i]; g[++cnt].push_back(w[i]); dfs(j,-1); sort(g[cnt].begin(),g[cnt].end()); } flow/=(int)g[1].size(); ll ans=0; for(i=0;i<(int)g[1].size();i++){ ll sum=0; for(int j=1;j<=cnt;j++){ sum+=g[j][i]; } if(sum>=flow) break; ans+=(flow-sum); } cout<<ans<<endl; }
View Code