zoukankan      html  css  js  c++  java
  • BZOJ 2055 80人环游世界 有上下界最小费用可行流

    题意:

        现在有这么一个m人的团伙,也想来一次环游世界。 他们打算兵分多路,游遍每一个国家。
        因为他们主要分布在东方,所以他们只朝西方进军。设从东方到西方的每一个国家的编号依次为1...N。假若第i个人的游历路线为P1、P2......Pk(0≤k≤N),则P1<P2<......<Pk。
        众所周知,中国相当美丽,这样在环游世界时就有很多人经过中国。我们用一个正整数Vi来描述一个国家的吸引程度,Vi值越大表示该国家越有吸引力,同时也表示有且仅有Vi个人会经过那一个国家。
        为了节省时间,他们打算通过坐飞机来完成环游世界的任务。同时为了省钱,他们希望总的机票费最小。
    1<= N < =100 ,1<= M <= 79

    分析:

      又一次用到了我们强大的拆点大法。

      我们把每个国家i拆点,拆成入点和出点,入点向出点连上下界均为Vi,表示这个国家有且仅有Vi个人经过。

      建立一个中转节点s,从源点S向s点连上界为m下界为0的边,代表总人数,然后从s点向每个国家的入点连容量无限的边,然后每个国家的出点向T点连容量无限的边。

      以上所有边费用都为0.

      接下来,如果i到j有航线,那么就从i的出点到j的入点连流量无限费用为机票价格的边。

      最后按照可行流建边,跑最小费用最大流即可。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;int S,T,tot=0;
     3 const int N=505,M=500005,inf=0x3f3f3f3f;
     4 struct node{int y,f,c,nxt;}e[M];int c=1,v[N];
     5 int h[N],q[M],d[N],n,m,s,t,pre[N];bool vis[N];
     6 void add(int x,int y,int z,int w){
     7     e[++c]=(node){y,z,w,h[x]};h[x]=c;
     8     e[++c]=(node){x,0,-w,h[y]};h[y]=c;
     9 } bool spfa(){
    10     for(int i=0;i<=T;i++) d[i]=inf;
    11     int l=1,r=0;q[++r]=S;vis[S]=1;d[S]=0;
    12     while(l<=r){ 
    13         int x=q[l++];vis[x]=0;
    14         for(int i=h[x],y;i;i=e[i].nxt)
    15         if(d[y=e[i].y]>d[x]+e[i].c&&e[i].f){
    16             d[y]=d[x]+e[i].c;pre[y]=i;
    17             if(!vis[y]) q[++r]=y,vis[y]=1;
    18         }
    19     } return (d[T]!=inf);
    20 } void aug(){ int x=inf;
    21     for(int i=pre[T];i;i=pre[e[i^1].y]) 
    22     x=min(x,e[i].f);
    23     for(int i=pre[T];i;i=pre[e[i^1].y])
    24     tot+=x*e[i].c,e[i].f-=x,e[i^1].f+=x;
    25 } int main(){
    26     scanf("%d%d",&n,&m);s=0;
    27     S=201,T=202;add(S,s,m,0);
    28     for(int i=1,x;i<=n;i++)
    29     scanf("%d",&x),add(s,i,inf,0),
    30     v[i]-=x,v[i+n]+=x;
    31     for(int i=1;i<=n;i++)
    32     for(int j=i+1,x;j<=n;j++){
    33         scanf("%d",&x);
    34         if(~x) add(i+n,j,inf,x);
    35     } for(int i=1;i<=n*2;i++)
    36     v[i]>0?add(S,i,v[i],0):
    37     (v[i]?add(i,T,-v[i],0):(void)0);
    38     while(spfa()) aug();
    39     printf("%d
    ",tot);return 0;
    40 }
    有上下界最小费用可行流
  • 相关阅读:
    利用django创建一个投票网站(二)
    利用django创建一个投票网站(一)
    django models进行数据库增删查改
    用pyspider爬淘宝MM照片
    爬虫实现模拟登陆豆瓣
    python-study-32
    python-study-31
    python-study-30
    python-周考2
    python-周考3
  • 原文地址:https://www.cnblogs.com/Alan-Luo/p/10256806.html
Copyright © 2011-2022 走看看