zoukankan      html  css  js  c++  java
  • bzoj2324 [ ZJOI2011 ] -- 费用流

    先用floyd求出不经过大于i或大于j的点的i,j间最短路径,然后考虑这样建图:

    对于每个点i,将其拆分成i、i',连边:

    s -> i' 容量为INF,费用为0

    s -> 1 容量为k,费用为0

    i' -> j 容量为1,费用为dist[i][j]

    i -> t 容量为1,费用为0

    此时这张图的最小费用最大流就是答案。

    代码: 

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 #define N 400
     6 #define M 20010
     7 #define INF 2147483647
     8 struct Edge{
     9     int c,w,f,t,nx;
    10 }e[M<<1],e1[M<<1];
    11 int i,j,k,x,y,z,n,m,h[N],H[N],d[N],s,di[N][N],p[N],q[M],Min[N],a[N],l,r,t,Num=1,Ans,K;
    12 bool b[N];
    13 inline int _Min(int x,int y){return x<y?x:y;}
    14 inline void Add(int x,int y,int c,int w){
    15     e[++Num].t=y;e[Num].f=x;e[Num].c=c;e[Num].w=w;e[Num].nx=h[x];h[x]=Num;
    16     e[++Num].t=x;e[Num].f=y;e[Num].c=0;e[Num].w=-w;e[Num].nx=h[y];h[y]=Num;
    17 }
    18 inline bool Spfa(){
    19     memset(b,0,sizeof(b));
    20     memset(d,127,sizeof(d));
    21     l=0;q[r=1]=s;d[s]=0;Min[s]=INF;
    22     while(l<r){
    23         int x=q[++l];
    24         b[x]=0;
    25         for(int i=h[x];i;i=e[i].nx)
    26         if(e[i].c>0&&d[e[i].t]>d[x]+e[i].w){
    27             d[e[i].t]=d[x]+e[i].w;
    28             p[e[i].t]=i;
    29             Min[e[i].t]=_Min(Min[x],e[i].c);
    30             if(!b[e[i].t]){
    31                 b[e[i].t]=1,q[++r]=e[i].t;
    32             }
    33         }
    34     }
    35     if(d[t]>2000000000)return 0;
    36     Ans+=d[t]*Min[t];
    37     for(int i=p[t];i;i=p[e[i].f])e[i].c-=Min[t],e[i^1].c+=Min[t];
    38     return 1;
    39 }
    40 int main()
    41 {
    42     scanf("%d%d%d",&n,&m,&K);t=((++n)<<1)|1;
    43     memset(di,63,sizeof(di));
    44     for(i=1;i<=m;i++){
    45         scanf("%d%d%d",&x,&y,&z);
    46         if(z<di[++x][++y])di[x][y]=di[y][x]=z;
    47     }
    48     Add(s,1,K,0);
    49     for(i=2;i<=n;i++)Add(i,t,1,0),Add(s,i+n,1,0);
    50     for(k=1;k<=n;k++)
    51     for(i=1;i<=n;i++)
    52     for(j=1;j<=n;j++)
    53     if(i!=j){
    54         if(di[i][k]+di[k][j]<di[i][j])di[i][j]=di[i][k]+di[k][j];
    55         if(k==j&&j>i&&di[i][j]<1000000000)Add(i==1?1:n+i,j,INF,di[i][j]);
    56     }
    57     n=t;
    58     while(Spfa());
    59     printf("%d",Ans);
    60     return 0;
    61 }
    bzoj2324
  • 相关阅读:
    python 合并 Excel 单元格
    python 设置 Excel 表格的行高和列宽
    Python 用 openpyxl 模块统计 Excel 表格中的数据,以字典形式写入 py 文件
    python 打印字母阶梯和金字塔
    python 用 openpyxl 读取 Excel 表格中指定的行或列
    Python 的 filter() 函数
    Python 的 map() 函数
    python 之 range() 函数
    python 的 reduce() 函数
    python 之 lambda 函数
  • 原文地址:https://www.cnblogs.com/gjghfd/p/6544782.html
Copyright © 2011-2022 走看看