• bzoj2039: [2009国家集训队]employ人员雇佣(最小割)


    2039: [2009国家集训队]employ人员雇佣

    题目:传送门

    题解:

       这一题一开始看前面以为是和最大获利一样。。

       双倍经验啊!!!美滋滋~

       然后发现自己漏了一个条件,还有敌对公司这种操作666~

       然后认真的再想了一下,正权和-最小割!!!

       本蒟蒻是这样理解的:

       我们把每个人的总获利(把二维转换为一维累加)和st连边

       雇佣的花费向ed连

       两两员工之间连2*E[i][j]的边,这个是关键。

       我们在跑最小割的时候,如果我们把i,j分离,其实是舍去了两倍收益的(敌对公司)

       这样一想,正权和-最小割输出答案。

       一A美滋滋~

    代码:

      

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<cmath>
      5 #include<algorithm>
      6 #define N 1100
      7 #define qread(x)x=read();
      8 using namespace std;
      9 typedef long long LL;
     10 inline int read()
     11 {
     12     int f=1,x=0;char ch;
     13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     15     return f*x;
     16 }
     17 struct node
     18 {
     19     int x,y,next,other;
     20     LL c;
     21 }a[2100000];int last[1100000],len;
     22 void ins(int x,int y,LL c)
     23 {
     24     int k1,k2;
     25     len++;k1=len;
     26     a[len].x=x;a[len].y=y;a[len].c=c;
     27     a[len].next=last[x];last[x]=len;
     28     
     29     len++;k2=len;
     30     a[len].x=y;a[len].y=x;a[len].c=0;
     31     a[len].next=last[y];last[y]=len;
     32     
     33     a[k1].other=k2;
     34     a[k2].other=k1;
     35 }
     36 int n,st,ed,head,tail;
     37 int s[1100000];
     38 LL d[1100000];
     39 int list[1100000],h[1100000];
     40 bool bt_h()
     41 {
     42     memset(h,0,sizeof(h));h[st]=1;
     43     list[1]=st;head=1;tail=2;
     44     while(head!=tail)
     45     {
     46         int x=list[head];
     47         for(int k=last[x];k;k=a[k].next)
     48         {
     49             int y=a[k].y;
     50             if(h[y]==0 && a[k].c>0)
     51             {
     52                 h[y]=h[x]+1;
     53                 list[tail++]=y;
     54             }
     55         }
     56         head++;
     57     }
     58     if(h[ed]>0)return true;
     59     else return false;
     60 }
     61 int find_flow(int x,LL flow)
     62 {
     63     if(x==ed)return flow;
     64     LL s=0,t;
     65     for(int k=last[x];k;k=a[k].next)
     66     {
     67         int y=a[k].y;
     68         if((h[y]==h[x]+1) && a[k].c>0  && s<flow)
     69         {
     70             t=find_flow(y,min(a[k].c,flow-s));
     71             s+=t;
     72             a[k].c-=t;a[a[k].other].c+=t;            
     73         }
     74     }
     75     if(s==0)h[x]=0;
     76     return s;
     77 }
     78 int main()
     79 {
     80     qread(n);st=0;ed=n+1;
     81     int sum=0;
     82     len=0;memset(last,0,sizeof(last));
     83     for(int i=1;i<=n;i++)
     84     {
     85         LL x;
     86         scanf("%lld",&x);
     87         ins(i,ed,x);
     88     }
     89     for(int i=1;i<=n;i++)
     90     {
     91         for(int j=1;j<=n;j++)
     92         {
     93             LL x;
     94             scanf("%lld",&x);
     95             if(i==j)continue;
     96             sum+=x;d[i]+=x;
     97             ins(i,j,x*2);
     98         }
     99     }
    100     for(int i=1;i<=n;i++)ins(st,i,d[i]);
    101     LL ans=0;
    102     while(bt_h())ans+=find_flow(st,999999999);
    103     printf("%lld",sum-ans);
    104     return 0;
    105 }

      

  • 相关阅读:
    Y+的一些讨论
    MATLAB中FFT的使用方法
    插入排序、冒泡排序、选择排序——转载
    输出控制中时间延迟的几种方法
    模拟通信调制方式与通信设备
    模拟通信主要特点
    模拟通信数字信号
    模拟通信
    传真存储变换设备与入网方式
    静止图像通信
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8093598.html
Copyright © 2020-2023  润新知