• [洛谷P3288][SCOI2014][BZOJ3597]方伯伯运椰子(网络流+图论)


    Address

    Solution

    • \(c_i\) 看作边 \((u_i,v_i)\) 的流量,并将每条边的容量都看作 \(∞\)
    • \(a_i\) 看作把边 \((u_i,v_i)\) 增广 \(1\) 单位流量的花费,\(b_i\) 看作将 \((u_i,v_i)\) 退 \(1\) 单位流量的花费,也就是把边 \((v_i,u_i)\) 增广 \(1\) 单位流量的花费。
    • \(d_i\) 看作把边 \((u_i,v_i)\) 增广 \(1\) 单位流量的代价,同时也看作把边 \((v_i,u_i)\) 增广 \(1\) 单位流量的收益
    • \(res=X-Y\),显然 \(\lfloor\)\((u_i,v_i)\) 增广 \(1\) 单位流量 \(\rfloor\)\(res\) 的贡献是 \(-b_i-d_i\)\(\lfloor\)\((v_i,u_i)\) 增广 \(1\) 单位流量 \(\rfloor\)\(res\) 的贡献是 \(d_i-a_i\)
    • 注意 \(c_i=0\) 时,不能增广 \((v_i,u_i)\)
    • 先按上面所说的建好一张新图。
    • 题目要求流量不能变少,又因为流量变多肯定不优,所以我们要让流量不变。
    • 也就是说我们要增广一些环。
    • 看到 \((X-Y)/k\),显然的分数规划模型。
    • 二分答案,判断是否 \(res/k≥mid\),即是否 \(res-mid*k≥0\)
    • 考虑将新图上的每条边减去 \(mid\),然后如果图上存在一个环使得边权和非负,那么 \(res/k≥mid\)

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    template <class t>
    inline void read(t & res)
    {
       char ch;
       while (ch = getchar(), !isdigit(ch));
       res = ch ^ 48;
       while (ch = getchar(), isdigit(ch))
       res = res * 10 + (ch ^ 48);
    }
    
    const int e = 1e5 + 5;
    const double inf = 1e18, eps = 1e-4;
    int n, m, adj[e], nxt[e], go[e], num, s, cnt[e];
    double len[e], ans, dis[e];
    bool vis[e];
    
    inline void add(int x, int y, double v)
    {
       nxt[++num] = adj[x]; adj[x] = num; go[num] = y; len[num] = v;
    }
    
    inline bool check(double mid)
    {
       queue<int>q;
       int i;
       for (i = 1; i <= n + 2; i++) vis[i] = 1, dis[i] = 0, cnt[i] = 1, q.push(i);
       while (!q.empty())
       {
       	int u = q.front();
       	q.pop();
       	vis[u] = 0;
       	for (i = adj[u]; i; i = nxt[i])
       	{
       		int v = go[i];
       		if (dis[u] + len[i] - mid >= dis[v])
       		{
       			dis[v] = dis[u] + len[i] - mid;
       			cnt[v] = cnt[u] + 1;
       			if (cnt[v] >= n + 2) return 1;
       			if (!vis[v]) q.push(v), vis[v] = 1;
       		}
       	}
       }
       return 0;
    }
    
    int main()
    {
       int i, u, v, ai, bi, ci, di;
       read(n); read(m); m--;
       while (m--)
       {
       	read(u); read(v); read(ai); read(bi); read(ci); read(di);
       	add(u, v, -bi - di);
       	if (ci) add(v, u, di - ai);
       }
       read(u); read(s); read(ai); read(bi); read(ci); read(di);
       double l = 0, r = 1e9;
       while (r - l > eps)
       {
       	double mid = (l + r) / 2.0;
       	if (check(mid)) ans = l = mid;
       	else r = mid;
       }
       printf("%.2lf\n", ans);
       return 0;
    }
    
  • 相关阅读:
    mysql.pas
    mysql 动态创建(删除)数据库,表
    界面美化(来自网络)
    串口的一点知识(摘抄)
    移位操作
    快速排序
    oracle和sqlserver互訪
    ASP.NET 无法向会话状态服务器发出会话状态请求 错误的解决方法
    去除 word requirements 工具条
    C# 控件预处理键盘命令
  • 原文地址:https://www.cnblogs.com/cyf32768/p/12196051.html
Copyright © 2020-2023  润新知