[距离限制模型 & 最小割]TopCoder SRM590 DIV1 1000. FoxAndCity

这里写图片描述
——APIO2017何昊天《APIO2017 网络流建模及其应用》

上一题就是那个切糕

// BEGIN CUT HERE  

// END CUT HERE  
#line 5 "FoxAndCity.cpp"  
#include <vector>  
#include <list>  
#include <map>  
#include <set>  
#include <deque>  
#include <stack>  
#include <bitset>  
#include <algorithm>  
#include <functional>  
#include <numeric>  
#include <utility>  
#include <sstream>  
#include <iostream>  
#include <iomanip>  
#include <cstdio>  
#include <cmath>  
#include <cstdlib>  
#include <ctime>  
#include <cstring>
#include <queue>
using namespace std;

const int N=2000010,inf=1<<29;

int n,S,T,cnt,G[50*50],f[55][55],c[55][55];

struct edge{
  int t,nx,f;
}E[N];

inline void link(int x,int y,int f){
  //cerr<<'\t'<<x<<' '<<y<<' '<<f<<endl;
  E[++cnt].t=y; E[cnt].nx=G[x]; E[cnt].f=f; G[x]=cnt;
  E[++cnt].t=x; E[cnt].nx=G[y]; E[cnt].f=0; G[y]=cnt;
}

queue<int> Q;
int dis[50*50],cur[50*50];

inline bool bfs(){
  while(!Q.empty()) Q.pop();
  for(int i=0;i<=T;i++) dis[i]=-1;
  Q.push(S); dis[S]=0;
  while(!Q.empty()){
    int x=Q.front(); Q.pop();
    for(int i=G[x];i;i=E[i].nx)
      if(E[i].f && dis[E[i].t]==-1){
    dis[E[i].t]=dis[x]+1;
    if(E[i].t==T) return true;
    Q.push(E[i].t);
      }
  }
  return false;
}

int dfs(int x,int f){
  if(x==T || !f) return f;
  int used=0,w;
  for(int &i=cur[x];i;i=E[i].nx)
    if(E[i].f && dis[E[i].t]==dis[x]+1){
      w=dfs(E[i].t,min(E[i].f,f-used));
      E[i].f-=w; E[i^1].f+=w;
      if((used+=w)==f) return f;
    }
  if(!used) dis[x]=-1;
  return used;
}

class FoxAndCity{  
public:  
  int minimalCost(vector <string> linked, vector <int> want){
    memset(G,0,sizeof(G)); cnt=1; n=linked.size(); int t=1;
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
    f[i][j]=linked[i-1][j-1]=='Y';
    for(int i=2;i<=n;i++)
      for(int j=1;j<=n;j++) c[i][j]=++t;
    S=0; T=++t;
    link(S,1,0); link(1,T,inf);
    for(int i=2;i<=n;i++){
      for(int j=1;j<=n;j++){
    if(j==1)
      link(S,c[i][j],inf);
    else
      link(c[i][j-1],c[i][j],(j-1-want[i-1])*(j-1-want[i-1]));
      }
      link(c[i][n],T,inf);
    }
    for(int i=2;i<=n;i++)
      if(f[1][i]) link(c[i][2],1,inf);
    for(int i=2;i<=n;i++){
      for(int j=1;j<=n;j++){
    for(int k=i+1;k<=n;k++)
      if(f[i][k]){
        if(j+1<=n)
          link(c[k][j+1],c[i][j],inf);
        if(j-2>0)
          link(c[i][j-1],c[k][j-2],inf);
      }
      }
    }
    int ans=0;
    while(bfs()){
      for(int i=0;i<=T;i++) cur[i]=G[i];
      ans+=dfs(S,inf);      
    }
    return ans;
  }  
};  
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值