zoukankan      html  css  js  c++  java
  • bzoj 1449 [JSOI2009]球队收益(费用拆分,最小费用流)

    1449: [JSOI2009]球队收益

    Time Limit: 5 Sec  Memory Limit: 64 MB
    Submit: 547  Solved: 302
    [Submit][Status][Discuss]

    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


    Source

    【思路】

           费用拆分,最小费用最大流。

           由S向每场比赛连边(1,0),由每场比赛向两支队伍连边(1,0)。

           考虑在胜w场败l场的基础上再赢一场,则增加cost = ci*w^2+di*l^2-ci*(w+1)^2-di*(l+1)^2=2*ci*w+ci+di+2*di*l的收益。当w增加时cost是单调递增的,所以可以每次相应连一条(1,cost)的边然后w++,l--再次添边直到比赛全部胜利,初始时假设剩余比赛全输。

    【代码】

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 #include<vector>
      5 #define FOR(a,b,c) for(int a=(b);a<(c);a++)
      6 using namespace std;
      7 
      8 typedef long long LL ;
      9 const int maxn = 8000+10;
     10 const int INF = 1e9;
     11 
     12 struct Edge{ int u,v,cap,flow,cost;
     13 };
     14 struct zkw {
     15     int n,m,s,t;
     16     int vis[maxn],d[maxn];
     17     vector<int> G[maxn];
     18     vector<Edge> es;
     19     
     20     void init(int n) {
     21         this->n=n;
     22         es.clear();
     23         for(int i=0;i<n;i++) G[i].clear();
     24     }
     25     void AddEdge(int u,int v,int cap,int cost) {
     26         es.push_back((Edge){u,v,cap,0,cost});
     27         es.push_back((Edge){v,u,0,0,-cost});
     28         m=es.size();
     29         G[u].push_back(m-2);
     30         G[v].push_back(m-1);
     31     }
     32     bool spfa() {
     33         memset(vis,0,sizeof(vis));
     34         for(int i=0;i<n;i++) d[i]=INF;
     35         queue<int> q;
     36         d[t]=0 , vis[t]=1 , q.push(t);
     37         while(!q.empty()) {
     38             int u=q.front(); q.pop() , vis[u]=0;
     39             for(int i=0;i<G[u].size();i++) {
     40                 Edge& e=es[G[u][i]];
     41                 int v=e.v;
     42                 if(es[G[u][i]^1].cap && d[v]>d[u]-e.cost) {
     43                     d[v]=d[u]-e.cost;
     44                     if(!vis[v]) {
     45                         vis[v]=1;
     46                         q.push(v);
     47                     }
     48                 }
     49             }
     50         }
     51         return d[s]!=INF;
     52     }
     53     int dfs(int u,int a,LL& cost) {
     54         vis[u]=1;  if(u==t) return a;
     55         int used=0,w;
     56         for(int i=0;i<G[u].size();i++) {
     57             Edge& e=es[G[u][i]];
     58             int v=e.v;
     59             if(d[u]-e.cost==d[v] && !vis[v] && e.cap) {
     60                 w=dfs(v,min(a-used,e.cap),cost);
     61                 cost+=w*e.cost;
     62                 e.cap-=w , es[G[u][i]^1].cap+=w;
     63                 used+=w; if(used==a) return a;
     64             }
     65         }
     66         return used;
     67     }
     68     int Mincost(int s,int t,LL& cost) {
     69         this->s=s , this->t=t;
     70         int flow=0; cost=0;
     71         while(spfa()) {
     72             vis[t]=1;
     73             while(vis[t]) {
     74                 memset(vis,0,sizeof(vis));
     75                 flow+=dfs(s,INF,cost);
     76             }
     77         }
     78         return flow;
     79     }
     80 } mc;
     81 
     82 
     83 int n,m;
     84 int c[maxn],d[maxn],win[maxn],lose[maxn],in[maxn];
     85 
     86 int main() {
     87     scanf("%d%d",&n,&m);
     88     mc.init(n+m+2);
     89     int s=n+m,t=s+1;
     90     FOR(i,0,n)
     91         scanf("%d%d%d%d",&win[i],&lose[i],&c[i],&d[i]);
     92     int u,v;
     93     FOR(i,0,m) {
     94         scanf("%d%d",&u,&v);
     95         u--,v--; 
     96         in[u]++,in[v]++;
     97         mc.AddEdge(s,i,1,0);
     98         mc.AddEdge(i,m+u,1,0);
     99         mc.AddEdge(i,m+v,1,0);
    100     }
    101     LL ans=0;
    102     FOR(i,0,n) {
    103         lose[i]+=in[i];
    104         ans+=c[i]*win[i]*win[i]+d[i]*lose[i]*lose[i];
    105     }
    106     FOR(i,0,n) {
    107         FOR(j,0,in[i]) {
    108             mc.AddEdge(m+i,t,1,2*c[i]*win[i]+c[i]+d[i]-2*d[i]*lose[i]);
    109             lose[i]-- , win[i]++;
    110         }
    111     }
    112     LL cost;
    113     mc.Mincost(s,t,cost);
    114     printf("%lld",cost+ans);
    115     return 0;
    116 }
  • 相关阅读:
    Java 判断日期的方法
    HTTP Session例子
    Unity3D性能优化
    TCP学习之二:客户端与服务端的连接
    TCP学习之一:TCP网络编程概念
    TCP学习之三:客户端、服务端同步传输字符串
    TCP学习之四:传输协议
    Lua与.net的CLR相互调用
    HTC vive开发:关于手柄按键
    JavaSESocket编程之简易聊天系统
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5094858.html
Copyright © 2011-2022 走看看