Solution
LP对偶:
⎧⎩⎨⎪⎪fi,j∑jfi,j≤=bi,j∑jfj,imaximize{∑fi,j×costi,j}
vi,j+ϕi−ϕj≥costi,jminimize{∑vi,j×bi,j}
建立源点和汇点。这道题的话有这样的一些限值。
yi≥xi+ti−diyi≥xi,xj≥yiys+T≥xtminimize{∑di×ci}
把 xi,yi 看成变量,没有的 vi,j 把权值设置为 +∞ 。
去正权环后跑最小费用最大流。
// BEGIN CUT HERE
// END CUT HERE
#line 5 "Farmville.cpp"
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 111;
const ll INF = 1 << 30;
const ll INFll = 1ll << 58;
struct edge {
int to, next, cap, cost;
edge(int t = 0, int n = 0, int co = 0, int ca = 0):to(t), next(n), cost(co), cap(ca) {}
};
edge G[N * N * 2];
int head[N];
ll dis[N];
int vis[N], pre[N];
int t[N], c[N];
int mp[N][N];
int Gcnt, S, T;
ll W0;
int n, bud, ans, smt;
queue<int> Q;
class Farmville {
public:
inline int x(int i) { return i << 1; }
inline int y(int i) { return i << 1 | 1; }
inline bool SPFA(int S, int T) {
for (int i = 0; i <= y(n + 3); i++) dis[i] = -INFll;
Q.push(S); vis[S] = true; dis[S] = 0;
while (!Q.empty()) {
ll x = Q.front(); Q.pop();
vis[x] = false;
for (int i = head[x]; i; i = G[i].next) {
edge &e = G[i];
if (e.cap && e.cost + dis[x] > dis[e.to]) {
dis[e.to] = e.cost + dis[x];
pre[e.to] = i ^ 1;
if (!vis[e.to]) {
Q.push(e.to); vis[e.to] = true;
}
}
}
}
return dis[T] != -INFll;
}
inline ll MCMF(int S, int T) {
ll cost = 0; int f;
while (SPFA(S, T)) {
f = INF;
for (int u = T; u != S; u = G[pre[u]].to)
f = min(f, G[pre[u] ^ 1].cap);
cost += f * dis[T];
for (int u = T; u != S; u = G[pre[u]].to) {
G[pre[u] ^ 1].cap -= f;
G[pre[u]].cap += f;
}
}
return cost;
}
inline void Add(int from, int to, int cost, int cap) {
// printf("%d %d %d %d\n", from, to, cost, cap);
G[++Gcnt] = edge(to, head[from], cost, cap); head[from] = Gcnt;
// printf("%d %d %d %d\n", to, from, -cost, 0);
G[++Gcnt] = edge(from, head[to], -cost, 0); head[to] = Gcnt;
}
inline void AddEdge(int from, int to, int cost, int cap) {
if (cost > 0) {
Add(S, to, 0, cap); Add(from, T, 0, cap);
Add(to, from, -cost, cap); W0 += (ll)cost * cap;
} else Add(from, to, cost, cap);
}
inline bool Check(int ti) {
memset(head, 0, sizeof head);
W0 = 0; Gcnt = 1; smt = 0;
ll s = x(n + 1), t = y(n + 1);
S = x(n + 2); T = y(n + 2);
for (int i = 1; i <= n; i++) {
AddEdge(s, x(i), 0, INF);
AddEdge(y(i), t, 0, INF);
}
AddEdge(t, s, -ti, INF);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (i != j && mp[j][i])
AddEdge(y(i), x(j), 0, INF);
for (int i = 1; i <= n; i++) {
AddEdge(x(i), y(i), ::t[i], c[i]);
AddEdge(x(i), y(i), 0, INF);
}
W0 += MCMF(S, T);
return W0 <= bud;
}
int minTime(vector <string> s, vector <int> time, vector <int> cost, int budget) {
bud = budget; n = time.size(); smt = 0;
for (int i = 1; i <= n; i++) {
t[i] = time[i - 1];
c[i] = cost[i - 1];
for (int j = 1; j <= n; j++)
mp[i][j] = s[i - 1][j - 1] - '0';
smt += t[i];
}
int L = 0, R = smt, Mid;
while (L <= R) {
Mid = (L + R) >> 1;
if (Check(Mid)) R = (ans = Mid) - 1;
else L = Mid + 1;
}
return ans;
}
// 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(void) {
Farmville ___test;
___test.run_test(-1);
// ___test.test_case_3();
system("pause");
}
// END CUT HERE