• [洛谷P4329][COCI2006-2007#1] Bond


    题目大意:有$n$个人有$n$个任务,每个人执行每个任务有不同的成功率,每个人只能执行一个任务,求所有任务都执行的总的成功率。

    题解:可以跑最大费用最大流,把成功率取个$log$,最后$exp$回去就好了。

    卡点:1.费用流边流量修改写挂  

      2.为判断无解情况($exp(0)==1$)  

      3.题目中没有卡一个任务没有人可以完成或者一个人什么任务都完不成的情况(原做法是状压)


    C++ Code:

    #include <cstdio>
    #include <cmath>
    #define maxn 50
    using namespace std;
    const int inf = 0x3f3f3f3f;
    int n;
    int H[maxn];
    
    int head[maxn], cnt = 2;
    struct Edge {
        int to, nxt, w;
        double cost;
    } e[maxn * maxn << 1];
    void add(int a, int b, int c, double d) {
        e[cnt] = (Edge) {b, head[a], c, d}; head[a] = cnt;
        e[cnt ^ 1] = (Edge) {a, head[b], 0, -d}; head[b] = cnt ^ 1;
        cnt += 2;
    }
    
    int st, ed, MF;
    double d[maxn];
    bool inq[maxn];
    int q[maxn << 2], h, t;
    int pre[maxn];
    inline double min(double a, double b) {return a < b ? a : b;}
    bool spfa() {
        for (int i = st; i <= ed; i++) d[i] = -inf;
        d[q[h = t = 0] = st] = 0;
        while (h <= t) {
            int u = q[h++];
            inq[u] = false;
            for (int i = head[u]; i; i = e[i].nxt) {
                int v = e[i].to;
                if (e[i].w && d[v] < d[u] + e[i].cost) {
                    d[v] = d[u] + e[i].cost;
                    pre[v] = i;
                    if (!inq[v]) {
                        inq[v] = true;
                        q[++t] = v;
                    }
                }
            }
        }
        return d[ed] > -inf / 10;
    }
    double update() {
        int mf = inf;
        for (int i = pre[ed]; i; i = pre[e[i ^ 1].to]) mf = min(mf, e[i].w);
        for (int i = pre[ed]; i; i = pre[e[i ^ 1].to]) e[i].w -= mf, e[i ^ 1].w += mf;
        MF += mf;
        return mf * d[ed];
    }
    void MCMF() {
        double ans = 0;
        while (spfa()) ans += update();
        if (MF != n) puts("0");
        else printf("%.6lf
    ", exp(ans) * 100.0);
    }
    
    int main() {
        scanf("%d", &n);
        st = 0, ed = n << 1 | 1;
        for (int i = 1; i <= n; i++) {
            add(st, i, 1, 0);
            int tmp = 0;
            for (int j = 1; j <= n; j++) {
                int a;
                scanf("%d", &a);
                tmp += a;
                H[j] += a;
                add(i, j + n, 1, log(a / 100.0));;
            }
            add(i + n, ed, 1, 0);
        }
        MCMF();
        return 0;
    }
    
  • 相关阅读:
    复(学)习化学时突然的一个 idea
    [BZOJ3032]七夕祭
    [BZOJ3781]小B的询问
    [BZOJ4103][Thu Summer Camp 2015]异或运算
    [BZOJ4817][Sdoi2017]树点涂色
    [BZOJ2506]calc
    [BZOJ1283]序列
    win 解除鼠标右键关联
    linux 常用shell命令之wc
    shell cat 合并文件,合并数据库sql文件
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/9532858.html
Copyright © 2020-2023  润新知