• 【BZOJ 2324】[ZJOI2011]营救皮卡丘 费用流


    本人实行诱骗拐卖(利用自然分层与实际意义),正解拼接补充(充分利用最大流限制(不浪费任何一个走出去的机会而不是不浪费任何一个已有的流)与问题转换)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    const int N=155;
    const int M=20010;
    const int K=12;
    const int Inf=0x3f3f3f3f;
    const int treat=1000000;
    const int P=N*2;
    const int E=N*N*2;
    int n,m,k;
    int via[N][N];
    struct V{
      int to,next,f,c;
    }c[E];
    int head[P],t=1;
    inline void add(int x,int y,int z,int _){
      c[++t].to=y,c[t].next=head[x],c[t].f=z,c[t].c=_,head[x]=t;
    }
    int dis[P],anc[P];
    int q[P],front,back;
    bool in[P];
    int S,T;
    inline bool spfa(){
      memset(dis,0x3f,sizeof(dis));
      in[S]=true,q[back++]=S,dis[S]=0;
      if(back==P)back=0;
      while(front!=back){
        int x=q[front++];in[x]=false;
        if(front==P)front=0;
        for(int i=head[x];i;i=c[i].next)
          if(c[i].f&&dis[x]+c[i].c<dis[c[i].to]){
            dis[c[i].to]=dis[x]+c[i].c,anc[c[i].to]=i;
            if(!in[c[i].to]){
              q[back++]=c[i].to,in[c[i].to]=true;
              if(back==P)back=0;
            }
          }
      }
      return dis[T]!=Inf;
    }
    inline int shoot(){
      int f=Inf;
      for(int i=anc[T];i;i=anc[c[i^1].to])f=std::min(f,c[i].f);
      for(int i=anc[T];i;i=anc[c[i^1].to])c[i].f-=f,c[i^1].f+=f;
      return f*dis[T];
    }
    int main(){
      memset(via,0x3f,sizeof(via));
      scanf("%d%d%d",&n,&m,&k);
      ++n;
      for(int i=1,x,y,z;i<=m;++i){
        scanf("%d%d%d",&x,&y,&z);
        ++x,++y;
        via[x][y]=via[y][x]=std::min(via[x][y],z);
      }
      S=n+n+1,T=n+n+2;
      for(int i=1;i<=n;++i){
        via[i][i]=0;
        add(i,i+n,1,-treat),add(i+n,i,0,treat);
        add(i,i+n,k,0),add(i+n,i,0,0);
        add(i+n,T,k,0),add(T,i+n,0,0);
      }
      for(int a=1;a<=n;++a)
        for(int b=1;b<=n;++b)
          via[a][b]=std::min(via[a][b],via[a][1]+via[1][b]);
      for(int i=2;i<=n;++i){
        for(int a=1;a<=n;++a)
          for(int b=1;b<=n;++b)
            via[a][b]=std::min(via[a][b],via[a][i]+via[i][b]);
        for(int j=1;j<i;++j){
          add(j+n,i,k,via[j][i]);
          add(i,j+n,0,-via[i][j]);
        }
      }
      add(S,1,k,0);
      add(1,S,0,0);
      int ans=0;
      while(spfa())ans+=shoot();
      ans+=n*treat;
      printf("%d",ans);
      return 0;
    }
  • 相关阅读:
    html$css_day05
    html$css_day04
    html$css_day03
    html$css_day02
    html$css_day01
    日常笔记19/3/04-19/3/10
    堆排序
    js对象之XMLHttpReques对象学习
    前端页面显示问题解决步骤(方法)
    SpringBoot跨域小结
  • 原文地址:https://www.cnblogs.com/TSHugh/p/8016332.html
Copyright © 2020-2023  润新知