码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-12-10 13:06:39      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:最大流   bsp   分层   最大   scan   line   str   next   void   

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

#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;
}

 

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

标签:最大流   bsp   分层   最大   scan   line   str   next   void   

原文地址:http://www.cnblogs.com/TSHugh/p/8016332.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!