• Codeforces CodeCraft-20 (Div. 2) E贪心,费用流


    Codeforces CodeCraft-20 (Div. 2) E,费用流
    原题

    题意:

    现有n个人需要成为队员或者观众,一个team有p(<7)个位置,需要k个观众。
    每个人 当观众贡献ai ,当不同位置的队员分别贡献pij
    问如何安排贡献最大。

    思路:

    这个题官方题解状态压缩DP,这里考虑一个网络流做法。
    不考虑要选k个观众,显然就是一个简单的dp。
    因为还要选k个观众,需要要分析这个问题的性质。这里我们想一个贪心的思路,对队员按ai进行排序。
    先不考虑队员,则我们先选取topk的观众,加进来队员的选择,发现可以分为两种情况讨论:
    1 选取的队员在前k个收,我们则需要在(k,n]中再选择一个当观众,考虑只有p个队队员,实际上只需要在(k,k+p]中选一个代替他来当观众。

    2 选取的队员在后k个,则直接选择就好。但实际上只需要在topP中做出选择,只有一个p的时候就是最大的那个,多个p的时候涉及的选择,但是一定在topP之中。

    根据上述结论,我们可以建图通过费用流帮我们选择(当然dp也可以)。需要准备的节点主要包括P[i],tmp,O(p)个点,O(p^2)条边。具体建图见代码。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define X first
    #define Y second
    #define PB push_back
    #define LL long long
    #define pii pair<LL,LL>
    #define MEM(x,y) memset(x,y,sizeof(x))
    #define bug(x) cout<<"debug "#x" is "<<x<<endl;
    #define FIO ios::sync_with_stdio(false);
    #define ALL(x) x.begin(),x.end()
    #define LOG 20
    #define lson(x) ((x)<<1)
    #define rson(x) ((x)<<1|1)
    const int maxn=2e5;
    const LL inf = 2e9;
    const int MAXN = 200000;
    const int MAXM = 200000;
    const int INF = 0x3f3f3f3f;
    struct Edge{
        int to,next,cap,flow,cost;
    } edge[MAXM];
    int head[MAXN],tol,pre[MAXN],N;
    LL dis[MAXN];
    bool vis[MAXN];
    void init(int n){
        N = n;
        tol = 0;
        memset(head,-1,sizeof(head));
    }
    void addedge(int u,int v,int cap,int cost){
        edge[tol].to = v;edge[tol].cap = cap;edge[tol].cost = cost;edge[tol].flow = 0;edge[tol].next = head[u];
        head[u] = tol++;
        edge[tol].to = u;edge[tol].cap = 0;edge[tol].cost = -cost;edge[tol].flow = 0;edge[tol].next = head[v];
        head[v] = tol++;
    }
    bool spfa(int s,int t){
        queue<int>q;
        for(int i = 0; i < N; i++){
            dis[i] = INF;
            vis[i] = false;
            pre[i] = -1;
        }
        dis[s] = 0;
        vis[s] = true;
        q.push(s);
        while(!q.empty()){
            int u = q.front();
            q.pop();
            vis[u] = false;
            for(int i = head[u]; i != -1; i = edge[i].next){
                int v = edge[i].to;
                if(edge[i].cap > edge[i].flow &&dis[v] > dis[u] + edge[i].cost ){
                    dis[v] = dis[u] + edge[i].cost;
                    pre[v] = i;
                    if(!vis[v]){
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        //return dis[t]<=0;
        if(pre[t] == -1)return false;
        else return true;
    }
    
    int minCostMaxflow(int s,int t,LL &cost){
        int flow = 0;
        cost = 0;
        while(spfa(s,t)){
            LL Min = INF;
            for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]){
                if(Min > edge[i].cap - edge[i].flow)
                    Min = edge[i].cap - edge[i].flow;
            }
            for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]){
                edge[i].flow += Min;
                edge[i^1].flow -= Min;
                cost += edge[i].cost * Min;
            }
            flow += Min;
        }
        return flow;
    }
    
    pair<int,vector<int>> a[maxn];
    int main(){
        FIO;
        int n,p,k,x;
        cin>>n>>p>>k;
        set<int> e;
        int cnt = n;
        int P[10];
        for(int i=0;i<p;i++) P[i] = cnt++;
        int E = cnt++, S = cnt++, tmp = cnt++;
        init(cnt);
        for(int i=0;i<n;i++)cin>>a[i].X;
        for(int i=0;i<n;i++)for(int j=0;j<p;j++) cin>>x,a[i].Y.PB(x);
        sort(a,a+n,greater<pair<int,vector<int>>>());
        for(int i=0;i<p;i++){
            addedge(S,P[i],1,0);
            vector<pii> v;
            for(int j=0;j<k;j++)v.PB({-a[j].Y[i]+a[j].X,j});
            sort(ALL(v));
            for(int j=0;j<p&&j<v.size();j++) addedge(P[i],v[j].Y,1,v[j].X),addedge(v[j].Y,tmp,1,0);
            v.clear();
            for(int j=k;j<n;j++)v.PB({-a[j].Y[i],j});
            sort(ALL(v));
            for(int j=0;j<v.size()&&j<p;j++) addedge(P[i],v[j].Y,1,v[j].X),e.insert(v[j].Y);
        }
        for(int j=k;j<k+p;j++) addedge(tmp,j,1,-a[j].X),e.insert(j);
        for(int i:e) addedge(i,E,1,0);
        LL ans;
        minCostMaxflow(S,E,ans);
        ans = -ans;
        for(int i=0;i<k;i++) ans+=a[i].X;
        cout<<ans<<endl;
    	return 0;
    }
    
    
  • 相关阅读:
    Wazuh配置电子邮件警报(SMTP)
    kafka 分区重新分配脚本
    shell并发及控制并发数
    python2和python3使用pyhive
    k8s1.17安装gitlab
    nginx ssl证书 BEGIN PRIVATE KEY 转换为BEGIN RSA PRIVATE KEY
    Datax:阿里云hbase数据导入到自建hbase集群
    python3连接impala(centos7)
    Effective Java2读书笔记-类和接口(五)
    Effective Java2读书笔记-类和接口(四)
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/12435863.html
Copyright © 2020-2023  润新知