2020牛客暑期多校训练营(一) H.Minimum-cost Flow

因为题中每条边的容量都是相同的,所以每条增广路的最大容量也都相同,且等于每条边的容量。我们假设每条边的最大容量为1,跑一遍费用流,就可以求出每条增广路的花费。

对于题中的每个询问,每条增广路的容量为u/v,所需最大流为1。可以转化为每条路的容量为u,所需最大流为v。假设v=a*u+b(b<u),我们可以将上述求出的增广路每条容量扩为u,取前a条的所有容量,第a+1条的b容量。

最后,由于我们求出的最大流为v,总费用应除以v。(读入卡cin

#include

using namespace std;
#define lowbit(x) ((x)&(-x))
#define REP(i, a, n) for(int i=a;i<=(n);i++)
#define IOS ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
typedef pair P;

const int maxn = 1e5 + 10;
const int N = 1e2 + 10;
const int M = 1e3 + 10;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const int mod2 = 998244353;
const int mod3 = 1e9 + 9;
const int hash1 = 131;
const int hash2 = 13331;
const double eps = 1e-6;
int head[N], ver[M], nxt[M], edge[M], cost[M];
int tot = 1;
int d[N], incf[N], pre[N];
int vis[N];

void add(int x, int y, int z, int c)
{
    ver[++tot] = y, edge[tot] = z, cost[tot] = c, nxt[tot] = head[x], head[x] = tot;
    ver[++tot] = x, edge[tot] = 0, cost[tot] = -c, nxt[tot] = head[y], head[y] = tot;
}

int s, t;
vector path;

bool spfa()
{
    queue q;
    memset(d, inf, sizeof(d));
    memset(vis, 0, sizeof(vis));
    q.push(s);
    d[s] = 0, vis[s] = 1;
    incf[s] = 1 << 30;
    while (!q.empty())
    {
        int x = q.front();
        q.pop();
        vis[x] = 0;
        for (int i = head[x]; i; i = nxt[i])
        {
            if (!edge[i])
                continue;
            int y = ver[i];
            if (d[y] > d[x] + cost[i])
            {
                d[y] = d[x] + cost[i];
                incf[y] = min(incf[x], edge[i]);
                pre[y] = i;
                if (!vis[y])
                    vis[y] = 1, q.push(y);
            }
        }
    }
    if (d[t] == inf)
        return false;
    return d[t];
}

int maxflow, ans;

void update()
{
    path.push_back(d[t]);//记录每条增广路的花费
    int x = t;
    while (x != s)
    {
        int i = pre[x];
        edge[i] -= incf[t];
        edge[i ^ 1] += incf[t];
        x = ver[i ^ 1];
    }
    maxflow += incf[t];
    ans += d[t] * incf[t];

}

ll sumd[N];

int main()
{
    int n, m;
    while (scanf("%d%d", &n, &m) != EOF)
    {
        path.clear();
        memset(head, 0, sizeof(head));
        tot = 1;
        for (int i = 1; i <= m; i++)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            add(a, b, 1, c);
        }
        s = 1, t = n;
        while (spfa())
            update();
        for (int i = 0; i < path.size(); i++)
        {
            sumd[i + 1] = sumd[i] + path[i];
        }
        int q;
        scanf("%d", &q);
        int u, v;
        for (int i = 1; i <= q; i++)
        {
            scanf("%d%d", &u, &v);
            if (u * path.size() < v)
            {
                puts("NaN");
                continue;
            }
            ll a = v / u;
            ll b = v % u;
            ll ans = sumd[a] * u + path[a] * b;
            ll x = __gcd((ll) v, ans);
            printf("%lld/%lld\n", ans / x, v / x);
        }

    }
    return 0;
}

 

你可能感兴趣的:(网络流)