1 条题解

  • 0
    @ 2026-5-9 16:15:53

    打了网络流标签却不用网络流板子的题。
    先说一个简单问题:求给定图平均边权最小的环。
    这个比较典,二分平均边权 xx,将图中所有边边权减小 xx,只需判图中是否有负环即可,spfa。
    显然最优环一定是简单环(否则将环分裂,必有一个不劣)。
    然后想这个问题,显然交通量无法增加(因为从起点出发的边不可调整),同时要求不能减少,故只能不变。
    考虑残量网络,对于每一条可修改的边,增大流量相当于花 b+db+d 的代价增加 11 的流量,减小流量(要求初始流量不为零)相当于花 ada-d 的代价减小 11 的流量(即反向边增大 11 的流量)。
    为保持流量平衡,必然修改环。为使最优调整比率最大,显然只能动 11 个平均边权最小的环。使用上述方法即可。
    复杂度最坏 O(nmh)O(nmh)hh 为二分次数,可过。

    #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
    上传者