[LP对偶费用流] SRM 676 div1 Farmville

二分答案T之后转化成求最小费用
加超级源和超级汇
记每个植物生长的时间为xi,结束的时间为yi,减少的时间为di。
那么限制为 yi>=xi+ti-di, yi>=xi,xj>=yi, ys+T>=xt, 最小化sum di*ci

然后直接对偶成最大费用循环流

这里写图片描述

在目标函数中不存在的,把权值设为inf

// BEGIN CUT HERE  
#include<conio.h>
#include<sstream>
// END CUT HERE  
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<string>
#include<set>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;

const int N=1005;
const int M=100005;

struct edge{
  int u,v,w,f,next;
}G[M];
int head[N],inum=1;
#define V G[p].v
inline void add(int u,int v,int w,int f,int p){
  G[p].u=u; G[p].v=v; G[p].w=w; G[p].f=f; G[p].next=head[u]; head[u]=p;
}
inline void link(int u,int v,int w,int f){
  add(u,v,w,f,++inum),add(v,u,-w,0,++inum);
}
inline void clear(){
  cl(head); inum=1;
}

int S,T;
ll dis[N]; int pre[N],ins[N];
int Q[1000005],l,r;

ll Mincost;

inline bool SPFA(){
  for (int i=1;i<=T;i++) dis[i]=-1LL<<60,pre[i]=0,ins[i]=0;
  l=r=-1; dis[S]=0; Q[++r]=S; ins[S]=1;
  while (l<r){
    int u=Q[++l]; ins[u]=0;
    for (int p=head[u];p;p=G[p].next)
      if (G[p].f && dis[V]<dis[u]+G[p].w){
    dis[V]=dis[u]+G[p].w; pre[V]=p;
    if (!ins[V]) Q[++r]=V,ins[V]=1;
      }
  }
  if (dis[T]==-1LL<<60) return 0;
  int minv=1<<30;
  for (int p=pre[T];p;p=pre[G[p].u])
    minv=min(minv,G[p].f);
  Mincost+=dis[T]*minv;
  for (int p=pre[T];p;p=pre[G[p].u])
    G[p].f-=minv,G[p^1].f+=minv;
  return 1;
}

int n,t[55],c[55];
char Map[55][55];
int bg;

#define x(i) ((i)*2-1)
#define y(i) ((i)*2)

inline bool check(int mid){
  clear();
  int s,t;
  s=2*n+1,t=2*n+2,S=2*n+3,T=2*n+4;
  for (int i=1;i<=n;i++)
    link(s,x(i),0,1<<30),link(y(i),t,0,1<<30);
  link(t,s,-mid,1<<30);
  for (int i=1;i<=n;i++)
    for (int j=1;j<=n;j++)
      if (i!=j && Map[j][i]=='1')
    link(y(i),x(j),0,1<<30);
  Mincost=0;
  int tmp=inum;
  for (int i=1;i<=n;i++){
    link(S,y(i),0,c[i]),link(x(i),T,0,c[i]),link(y(i),x(i),-::t[i],c[i]),Mincost+=(ll)c[i]*::t[i];
    link(x(i),y(i),0,1<<30);
  }
  while (SPFA());
  return Mincost<=bg;
}


class Farmville{
public:
  int minTime(vector <string> s, vector <int> time, vector <int> cost, int budget){
    n=s.size();
    for (int i=1;i<=n;i++)
      for (int j=1;j<=n;j++) Map[i][j]=s[i-1][j-1];
    int sum=0;
    for (int i=1;i<=n;i++) t[i]=time[i-1],c[i]=cost[i-1],sum+=t[i];
    bg=budget;
    int L=-1,R=sum,MID;
    while (L+1<R)
      if (check(MID=(L+R)>>1))
    R=MID;
      else
    L=MID;
    return R;
  }


// BEGIN CUT HERE
    public:
    void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); if ((Case == -1) || (Case == 4)) test_case_4(); if ((Case == -1) || (Case == 5)) test_case_5(); }
    private:
    template <typename T> string print_array(const vector<T> &_V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = _V.begin(); iter != _V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
    void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
    void test_case_0() { string Arr0[] = {"000",
 "000",
 "000"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {25,15,10}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {1,2,3}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 50; int Arg4 = 6; verify_case(0, Arg4, minTime(Arg0, Arg1, Arg2, Arg3)); }
    void test_case_1() { string Arr0[] = {"0000",
 "1000",
 "0100",
 "0010"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {25,25,25,25}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {100,200,300,400}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 2800; int Arg4 = 74; verify_case(1, Arg4, minTime(Arg0, Arg1, Arg2, Arg3)); }
    void test_case_2() { string Arr0[] = {"01110",
 "00010",
 "00000",
 "00000",
 "10000"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {25,10,23,12,5}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {123,456,789,1011,1213}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 1000000000; int Arg4 = 0; verify_case(2, Arg4, minTime(Arg0, Arg1, Arg2, Arg3)); }
    void test_case_3() { string Arr0[] = {"00",
 "00"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {25,25}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {1000000000,1000000000}   ; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 1000000000; int Arg4 = 25; verify_case(3, Arg4, minTime(Arg0, Arg1, Arg2, Arg3)); }
    void test_case_4() { string Arr0[] = {"0000000000000000",
 "1000000000000000",
 "1000000000000000",
 "0100000000000000",
 "0110000000000000",
 "0010000000000000",
 "0001000000000000",
 "0001100000000000",
 "0000110000000000",
 "0000010000000000",
 "0000001100000000",
 "0000000110000000",
 "0000000011000000",
 "0000000000110000",
 "0000000000011000",
 "0000000000000110"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {24,25,23,25,23,24,25,24,23,22,25,24,23,25,23,25}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {82912,129482,235934,3294812,523942,460492,349281,592384,
109248,2305923,340945,2304934,582396,548935,767872,423981}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 87654321; int Arg4 = 49; verify_case(4, Arg4, minTime(Arg0, Arg1, Arg2, Arg3)); }
    void test_case_5() { string Arr0[] = {"000","100","110"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {3,18,1}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {242949,8471,54403957}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 53867; int Arg4 = 16; verify_case(5, Arg4, minTime(Arg0, Arg1, Arg2, Arg3)); }

// END CUT HERE

};

// BEGIN CUT HERE
int main(){
 Farmville ___test;
 ___test.run_test(-1);
 getch() ;
 return 0;
}
// END CUT HERE
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值