zoukankan      html  css  js  c++  java
  • hdu 3917(最大权闭包)最大获利

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3917

    思路:就是一个最大权闭包的模型,解法为求最小割,构图方法以公司为点,如果公司之间有关系,则连一条容量为无穷的有向边,对每个公司,如果该公司收益为正,则从vs到该公司连一条容量为收益的有向边,如果为负,向vt连一条容量为该公司收益绝对值的边,为0时选和不选不影响结果,可以舍去。其消费为所有收益和-所选割中正收益-所有割中负收益(减去负的即为加上绝对值),然后求出最小割,最后相减即可。(胡伯涛的论文《最小割模型在信息学竞赛中的应用》里面有这个模型)

    View Code
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<vector>
      5 using namespace std;
      6 #define MAXN 5555
      7 #define MAXM 2222222
      8 #define inf 1<<30
      9 
     10 struct Edge{
     11     int v,cap,next;
     12 }edge[MAXM];
     13 
     14 int head[MAXN];
     15 int pre[MAXN];
     16 int cur[MAXN];
     17 int level[MAXN];
     18 int gap[MAXN];
     19 int NV,NE,vs,vt,n,m,f,sum;
     20 
     21 vector<int>st[MAXN],ed[MAXN];
     22 int tax[MAXN];
     23 
     24 void Insert(int u,int v,int cap,int cc=0){
     25     edge[NE].v=v;edge[NE].cap=cap;
     26     edge[NE].next=head[u];head[u]=NE++;
     27 
     28     edge[NE].v=u;edge[NE].cap=cc;
     29     edge[NE].next=head[v];head[v]=NE++;
     30 }
     31 
     32 
     33 int SAP(int vs,int vt){
     34     memset(pre,-1,sizeof(pre));
     35     memset(level,0,sizeof(level));
     36     memset(gap,0,sizeof(gap));
     37     for(int i=0;i<=NV;i++)cur[i]=head[i];
     38     int u=pre[vs]=vs,maxflow=0,aug=-1;
     39     gap[0]=NV;
     40     while(level[vs]<NV){
     41 loop:
     42         for(int &i=cur[u];i!=-1;i=edge[i].next){
     43             int v=edge[i].v;
     44             if(edge[i].cap&&level[u]==level[v]+1){
     45                 aug==-1?aug=edge[i].cap:aug=min(aug,edge[i].cap);
     46                 pre[v]=u;
     47                 u=v;
     48                 if(v==vt){
     49                     maxflow+=aug;
     50                     for(u=pre[u];v!=vs;v=u,u=pre[u]){
     51                         edge[cur[u]].cap-=aug;
     52                         edge[cur[u]^1].cap+=aug;
     53                     }
     54                     aug=-1;
     55                 }
     56                 goto loop;
     57             }
     58         }
     59         int minlevel=NV;
     60         for(int i=head[u];i!=-1;i=edge[i].next){
     61             int v=edge[i].v;
     62             if(edge[i].cap&&minlevel>level[v]){
     63                 cur[u]=i;
     64                 minlevel=level[v];
     65             }
     66         }
     67         if(--gap[level[u]]==0)break;
     68         level[u]=minlevel+1;
     69         gap[level[u]]++;
     70         u=pre[u];
     71     }
     72     return maxflow;
     73 }
     74 
     75 void Build(){
     76     for(int i=1;i<=m;i++){
     77         if(tax[i]>0)Insert(vs,i,tax[i]),sum+=tax[i];
     78         else if(tax[i]<0)Insert(i,vt,-tax[i]);
     79     }
     80     for(int i=1;i<=n;i++){
     81         for(int j=0;j<st[i].size();j++){
     82             for(int k=0;k<ed[i].size();k++){
     83                 Insert(ed[i][k],st[i][j],inf);//这里建边要注意了!(是以顶点i结尾的点所在的那个公司连以顶点i开始的所在的公司)
     84             }
     85         }
     86     }
     87 }
     88 
     89 
     90 int main(){
     91     while(~scanf("%d%d",&n,&m)&&(n+m)){
     92         int u,v,company,cost;
     93         for(int i=1;i<=n;i++)st[i].clear(),ed[i].clear();
     94         for(int i=1;i<=m;i++){
     95             scanf("%d",&tax[i]);
     96         }
     97         scanf("%d",&f);
     98         for(int i=1;i<=f;i++){
     99             scanf("%d%d%d%d",&u,&v,&company,&cost);
    100             st[u].push_back(company);
    101             ed[v].push_back(company);
    102             tax[company]-=cost;//要减去补偿给每个公司的money
    103         }
    104         memset(head,-1,sizeof(head));
    105         vs=0,vt=m+1,NE=0,NV=m+2,sum=0;
    106         Build();
    107         printf("%d\n",sum-SAP(vs,vt));
    108     }
    109     return 0;
    110 }
    111 
    112         
  • 相关阅读:
    团队作业3--需求改进&系统设计
    需求分析&原型设计
    团队项目作业1-团队展示
    结对编程
    APP案例分析之华为浏览器
    四则运算生成器做法思路
    关于PHP使用GD库生成的验证码无法在别处显示
    第二次课程心得
    两个程序代码
    5.8下午
  • 原文地址:https://www.cnblogs.com/wally/p/3071865.html
Copyright © 2011-2022 走看看