zoukankan      html  css  js  c++  java
  • bzoj 1449: [JSOI2009]球队收益

    Description

    Input

    Output

    一个整数表示联盟里所有球队收益之和的最小值。

    Sample Input

    3 3
    1 0 2 1
    1 1 10 1
    0 1 3 3
    1 2
    2 3
    3 1

    Sample Output

    43

    HINT

    solution

    设n为当前winsum,m为当前losesum

    这道题 有用的性质:

    1.不管 输还是赢 增加的收益永远是递增的

      Ci*(n+1)^2-Ci*n^2=2*n+1

    2.对于单个的一支球队来说,赢得永远比输的收益多

    技巧:

    由于从比赛节点 向球队结点连一条边之后,还会有两种情况,根本无法加权值

    所以先假设比赛的双方都输,然后改的时候只需要改赢得一方

    赢得一方 增加的收益=Ci*(win+1)^2+Di(lose-1)^2-Ci*win^2-Di*lose^2

    建图:S=0 T=n+m+1

    1.S向每场比赛连 w=1 cost=0 的边

    2.每场比赛向比赛双方连 w=1 cost=0 的边

    3.记录下每个球队参加的比赛场数 s

    每个球队 向T依次连 s条边,w=INF,cost按照一开始的winsum依次加   (这个比较难理解)

    这样加保证  既选择了最小费用,又不会影响对手的最小费用 (从球队向T依次连了多条边)(大佬命名其为 拆边法)

    最后跑MCMF即可

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 #include<iostream>
      5 #define mem(a,b) memset(a,b,sizeof(a))
      6 #define ll long long
      7 #define dd double
      8 using namespace std;
      9 const int INF=(1<<31)-1;
     10 inline int minn(int a,int b){return a<b?a:b;}
     11 struct son
     12 {
     13     int u,v,next;
     14     int w,cost;
     15 };
     16 son a1[1000006];
     17 int first[1000006],e;
     18 void addbian(int u,int v,int w,int cost)
     19 {
     20     a1[e].cost=cost;
     21     a1[e].v=v;
     22     a1[e].w=w;
     23     a1[e].u=u;
     24     a1[e].next=first[u];
     25     first[u]=e++;
     26 }
     27 void Link(int u,int v,int w,int cost)
     28 {
     29     addbian(u,v,w,cost);
     30     addbian(v,u,0,-cost);
     31 }
     32 
     33 int n,m,u,o;
     34 int win[5006],lose[5006],C[5006],D[5006];
     35 int a[5006],b[5006];
     36 int S,T;
     37 int ans;
     38 
     39 int flow[8006],flag[8006],d[8006],pre[8006];
     40 queue<int> q;
     41 bool spfa(int &fw,int &ct)
     42 {
     43     mem(d,0x7f/3);mem(flag,0);mem(flow,0x7f);mem(pre,0);
     44     int qqq=d[0];
     45     q.push(S);flag[S]=1;d[S]=0;
     46     while(!q.empty())
     47     {
     48         int now=q.front();q.pop();flag[now]=0;
     49         for(int i=first[now];i!=-1;i=a1[i].next)
     50         {
     51             int temp=a1[i].v;
     52             if(!a1[i].w||d[temp]<=d[now]+a1[i].cost)continue;
     53             d[temp]=d[now]+a1[i].cost;
     54             pre[temp]=i;
     55             flow[temp]=minn(flow[now],a1[i].w);
     56             if(!flag[temp])
     57             {
     58                 q.push(temp);
     59                 flag[temp]=1;
     60             }
     61         }
     62     }
     63     if(d[T]==qqq)return 0;
     64     fw+=flow[T];
     65     ct+=d[T]*flow[T];
     66     int now=T;
     67     while(now!=S)
     68     {
     69         a1[pre[now]].w-=flow[T];
     70         a1[pre[now]^1].w+=flow[T];
     71         now=a1[pre[now]].u;
     72     }
     73     return 1;
     74 }
     75 
     76 int MCMF()
     77 {
     78     int flow=0,cost=0;
     79     while(spfa(flow,cost));
     80     return cost;
     81 }
     82 
     83 void out11()
     84 {
     85     printf("
    ");
     86     for(int i=1;i<=m;++i)
     87     {
     88         printf("i=%d
    ",i);
     89         for(int j=first[i];j!=-1;j=a1[j].next)
     90           printf("%d ",a1[j].v);
     91         printf("
    ");
     92     }
     93     printf("
    ");
     94 }
     95 
     96 int main(){
     97     //freopen("1.txt","r",stdin);
     98     mem(first,-1);
     99     scanf("%d%d",&n,&m);
    100     for(int i=1;i<=n;++i)scanf("%d%d%d%d",&win[i],&lose[i],&C[i],&D[i]);
    101     S=0;T=n+m+1;
    102     for(int i=1;i<=m;++i)
    103     {
    104         Link(S,i,1,0);
    105         scanf("%d%d",&a[i],&b[i]);
    106         ++lose[a[i]];++lose[b[i]];
    107     }
    108     for(int i=1;i<=n;++i)
    109       ans+=( C[i]*win[i]*win[i]+D[i]*lose[i]*lose[i] );
    110     for(int i=1;i<=m;++i)
    111     {
    112         Link(i,m+a[i],1,0);
    113         Link(i,m+b[i],1,0);
    114         Link(a[i]+m,T,1, C[a[i]]*(2*win[a[i]]+1)-D[a[i]]*(2*lose[a[i]]-1) );
    115         ++win[a[i]];--lose[a[i]];
    116         Link(b[i]+m,T,1, C[b[i]]*(2*win[b[i]]+1)-D[b[i]]*(2*lose[b[i]]-1) );
    117         ++win[b[i]];--lose[b[i]];
    118     }
    119     //out11();
    120     //cout<<0;
    121     printf("%d",ans+MCMF());
    122     //while(1);
    123     return 0;
    124 }
    mk A_LEAF
  • 相关阅读:
    day4
    day3
    day2
    day1
    spring-boot-note
    spring-boot-cli
    jquery ajax rest invoke
    spring-boot
    docker mysql
    jpa OneToMany
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7263751.html
Copyright © 2011-2022 走看看