1 条题解
-
0
打了网络流标签却不用网络流板子的题。
先说一个简单问题:求给定图平均边权最小的环。
这个比较典,二分平均边权 ,将图中所有边边权减小 ,只需判图中是否有负环即可,spfa。
显然最优环一定是简单环(否则将环分裂,必有一个不劣)。
然后想这个问题,显然交通量无法增加(因为从起点出发的边不可调整),同时要求不能减少,故只能不变。
考虑残量网络,对于每一条可修改的边,增大流量相当于花 的代价增加 的流量,减小流量(要求初始流量不为零)相当于花 的代价减小 的流量(即反向边增大 的流量)。
为保持流量平衡,必然修改环。为使最优调整比率最大,显然只能动 个平均边权最小的环。使用上述方法即可。
复杂度最坏 , 为二分次数,可过。#include<bits/stdc++.h> using namespace std; int n,m; struct edge{ int v; double w; }; vector<edge>g[5005]; queue<int>q; int vis[5005]; double dis[5005]; bool h[5005]; bool spfa(int u){ memset(h,0,sizeof(h)); memset(vis,0,sizeof(vis)); fill(dis+1,dis+1+n,1e10); q=queue<int>(); dis[u]=0; q.push(u); vis[u]=1; while(!q.empty()){ int u=q.front(); q.pop(); vis[u]++; h[u]=0; if(vis[u]>n) return true; for(int i=0;i<g[u].size();i++){ if(dis[g[u][i].v]>dis[u]+g[u][i].w+1e-6){ dis[g[u][i].v]=dis[u]+g[u][i].w; if(!h[g[u][i].v]){ q.push(g[u][i].v); h[g[u][i].v]=1; } } } } return false; } int s; int main(){ cin>>n>>m; n+=2; for(int i=1;i<=m;i++){ int u,v,a,b,c,d; cin>>u>>v>>a>>b>>c>>d; if(c)g[v].push_back({u,a-d}); g[u].push_back({v,b+d}); if(u==n-1) s=v;//起点边不能改 } double l=-3e4,r=3e4; while(l+1e-4<r){ double m=(l+r)/2; for(int i=1;i<=n;i++){ for(int j=0;j<g[i].size();j++){ g[i][j].w-=m; } } if(spfa(s)) r=m; else l=m; for(int i=1;i<=n;i++){ for(int j=0;j<g[i].size();j++){ g[i][j].w+=m; } } } cout<<fixed<<setprecision(2)<<-l;//注意比率定义 return 0; }
- 1
信息
- ID
- 5262
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者