• cf 730i


    题意:有n个人,每个人有两个能力值,选a个人用它的第一个能力值,b个人用它的第二个能力值,每个人只能选一次,求一个方案使得能力值之和最大,并输出选择方案.

    题解:最小费用最大流,原点1向n个人每个人i+1连流量为1费用为0的边,在有两个点n+2和n+3,每个人i+1向点n+2连流量为1,费用为-能量值的边,向n+3连流量为1,费用为-能力值的边,n+2向汇点n+4连流量为a费用为0的边,n+3向汇点n+4连流量为b费用为0的边.

    注意:应该在跑完了费用流之后再输出路径,因为在过程之后总有可能有反向边,所以无法在过程中就确定最终路径.跑完了费用流之后,如果某一条边反向流不为0即表示有流量经过.

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<climits>
      5 #include<queue>
      6 #include<cmath>
      7 #define MAXP 3010
      8 #define MAXE 40500
      9 #define MIN(a,b) (a<b?a:b)
     10 using namespace std;
     11 int n,m;
     12 struct Edge
     13 {
     14     int s,t,f,c,next;
     15 };
     16 class MCMF
     17 {
     18 public:
     19     MCMF(int s,int t);
     20     void insert(int s,int t,int f,int c);
     21     bool spfa();
     22     void mcmf();
     23     void print();
     24 private:
     25     bool *isq;
     26     int s,t;
     27     int *dist;
     28     int ent;
     29     int cost,flow;
     30     int *head;
     31     int *pre;
     32     Edge *edge;
     33 };
     34 MCMF::MCMF(int s,int t)
     35 {
     36     this->s=s;
     37     this->t=t;
     38     ent=0;
     39     cost=0;
     40     flow=0;
     41     isq=new bool [MAXP];
     42     dist=new int[MAXP];
     43     head=new int[MAXP];
     44     edge=new Edge[MAXE];
     45     pre=new int[MAXE];
     46     memset(head,-1,sizeof(int)*MAXP);
     47 }
     48 void MCMF::insert(int s,int t,int f,int c)
     49 {
     50     edge[ent].s=s;edge[ent].t=t;edge[ent].f=f;
     51     edge[ent].c=c;edge[ent].next=head[s];head[s]=ent++;
     52     edge[ent].s=t;edge[ent].t=s;edge[ent].f=0;
     53     edge[ent].c=-c;edge[ent].next=head[t];head[t]=ent++;
     54 }
     55 bool MCMF::spfa()
     56 {
     57     memset(pre,-1,sizeof(int)*MAXE);
     58     for(int i=1;i<=t;i++)
     59     {
     60         isq[i]=false;
     61         dist[i]=INT_MAX;
     62     }
     63     queue<int>q;
     64     q.push(s);
     65     isq[s]=true;
     66     dist[s]=0;
     67     while(!q.empty())
     68     {
     69         int temp1=q.front();
     70         q.pop();
     71         isq[temp1]=false;
     72         for(int i=head[temp1];i!=-1;i=edge[i].next)
     73         {
     74             int temp2=edge[i].t;
     75             if(edge[i].f&&edge[i].c+dist[temp1]<dist[temp2])
     76             {
     77                 dist[temp2]=edge[i].c+dist[temp1];
     78                 pre[temp2]=i;
     79                 if(!isq[temp2])
     80                     q.push(temp2);
     81             }
     82         }
     83     }
     84     return pre[t]!=-1;
     85 }
     86 void MCMF::mcmf()
     87 {
     88     while(spfa())
     89     {
     90         int minn=INT_MAX;
     91         for(int i=pre[t];i!=-1;i=pre[i])
     92         {
     93             minn=MIN(minn,edge[i].f);
     94             i=edge[i].s;
     95         }
     96         flow+=minn;
     97         for(int i=pre[t];i!=-1;i=pre[i])
     98         {
     99             edge[i].f-=minn;
    100             edge[i^1].f+=minn;
    101             i=edge[i].s;
    102         }
    103         cost+=minn*dist[t];
    104     }
    105     cout<<-cost<<endl;
    106 }
    107 void MCMF::print()
    108 {
    109     for(int i=head[n+2];i!=-1;i=edge[i].next)
    110         if(edge[i].f==1&&edge[i].t!=n+4)
    111             printf("%d ",edge[i].t-1);
    112     printf("
    ");
    113     for(int i=head[n+3];i!=-1;i=edge[i].next)
    114         if(edge[i].f==1&&edge[i].t!=n+4)
    115             printf("%d ",edge[i].t-1);
    116 }
    117 int a,b;
    118 int main()
    119 {
    120     int s,t,c;
    121     scanf("%d%d%d",&n,&a,&b);
    122     MCMF *temp=new MCMF(1,n+4);
    123     for(int i=1;i<=n;i++)
    124         temp->insert(1,i+1,1,0);
    125     for(int i=1;i<=n;i++)
    126     {
    127         scanf("%d",&m);
    128         temp->insert(i+1,n+2,1,-m);
    129     }
    130     for(int i=1;i<=n;i++)
    131     {
    132         scanf("%d",&m);
    133         temp->insert(i+1,n+3,1,-m);
    134     }
    135     temp->insert(n+2,n+4,a,0);
    136     temp->insert(n+3,n+4,b,0);
    137     temp->mcmf();
    138     temp->print();
    139     return 0;
    140 }
  • 相关阅读:
    asp.net mvc 从数据库中读取图片
    给折腾ramdisk的朋友们一点建议
    docker安装Jenkins和构建python容器
    docker笔记
    接口加密方式
    Dockerfile常用命令
    北斗七星小队团队展示
    固件程序设计实验内容1.4
    Myod实验 20181328祝维卿
    电子公文系统团队作业(四):描述设计
  • 原文地址:https://www.cnblogs.com/lthb/p/6035511.html
Copyright © 2020-2023  润新知