• CF739E Gosha is hunting(费用流,期望)


    根据期望的线性性答案就是捕捉每一只精灵的概率之和。
    捕捉一只精灵的方案如下:
    1.使用一个(A)精灵球,贡献为(A[i])
    2.使用一个(B)精灵球,贡献为(B[i])
    3.使用一个(A)精灵球和一个(B)精灵球,贡献为(A[i]+B[i]-A[i]*B[i])
    然后我们可以这样建图:
    源点(S)向两个精灵球连容量为精灵球数量,费用为(0)的边。
    (A)精灵球向i连容量为(1),费用为(A[i])的边。
    (B)精灵球向i连容量为(1),费用为(B[i])的边。
    然后每一只精灵向T连一条容量为(1),费用为(0)的边和一条容量为(1),费用为(-A[i]*B[i])的边。
    然后跑最大费用流即可。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int N=2200;
    const double INF=1e9;
    const double eps=1e-8;
    int n,a,b,S,T;
    double A[N],B[N],ans,dis[N];
    bool vis[N];
    int cnt=1,head[N],from[N];
    struct edge{
        int to,nxt,flow;
        double cost;
    }e[N*8];
    void add_edge(int u,int v,int flow,double cost){
        cnt++;
        e[cnt].nxt=head[u];
        e[cnt].to=v;
        e[cnt].flow=flow;
        e[cnt].cost=cost;
        head[u]=cnt;
    }
    bool spfa(){
        for(int i=S;i<=T;i++)dis[i]=INF;
        dis[S]=0;
        queue<int> q;
        q.push(S);
        vis[S]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head[u];i;i=e[i].nxt){
                int v=e[i].to;
                if(dis[v]>dis[u]+e[i].cost+eps&&e[i].flow){
                    dis[v]=dis[u]+e[i].cost;
                    from[v]=i;
                    if(vis[v]==0)vis[v]=1,q.push(v);
                }
            }
        }
        if(dis[T]==INF)return false;
        int mn=INF;
        for(int i=T;i!=S;i=e[from[i]^1].to)
            mn=min(mn,e[from[i]].flow);
        ans+=dis[T]*mn;
        for(int i=T;i!=S;i=e[from[i]^1].to){
            e[from[i]].flow-=mn;
            e[from[i]^1].flow+=mn;
        }
        return true;
    }
    int main(){
        scanf("%d%d%d",&n,&a,&b);
        for(int i=1;i<=n;i++)scanf("%lf",&A[i]);
        for(int i=1;i<=n;i++)scanf("%lf",&B[i]);
        S=0;T=2+n+1;
        add_edge(S,1,a,0);add_edge(1,S,0,0);
        add_edge(S,2,b,0);add_edge(2,S,0,0);
        for(int i=1;i<=n;i++){
            add_edge(1,i+2,1,-A[i]);add_edge(i+2,1,0,A[i]);
            add_edge(2,i+2,1,-B[i]);add_edge(i+2,2,0,B[i]);
            add_edge(i+2,T,1,0);add_edge(T,i+2,0,0);
            add_edge(i+2,T,1,A[i]*B[i]);add_edge(T,i+2,0,-A[i]*B[i]);
        }
        while(spfa());
        printf("%.4lf",-ans);
        return 0;
    }
    
  • 相关阅读:
    使用ActivityGroup来切换Activity和Layout
    Fragment
    [Java]LeetCode297. 二叉树的序列化与反序列化 | Serialize and Deserialize Binary Tree
    [Swift]LeetCode298. 二叉树最长连续序列 $ Binary Tree Longest Consecutive Sequence
    [Swift]LeetCode296. 最佳开会地点 $ Best Meeting Point
    [Swift]LeetCode294. 翻转游戏之 II $ Flip Game II
    [Swift]LeetCode293. 翻转游戏 $ Flip Game
    [Swift]LeetCode291. 单词模式 II $ Word Pattern II
    [Postman]发出SOAP请求(18)
    [Postman]生成代码段(17)
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/10436202.html
Copyright © 2020-2023  润新知