[LP对偶][含正权环的最大费用流] SRM 676 div1 1000pts Farmville

来源:互联网 发布:js图片轮播思路 编辑:程序博客网 时间:2024/05/22 12:48

Solution

LP对偶:

fi,jjfi,j=bi,jjfj,imaximize{fi,j×costi,j}

vi,j+ϕiϕjcosti,jminimize{vi,j×bi,j}

建立源点和汇点。这道题的话有这样的一些限值。
yixi+tidiyixi,xjyiys+Txtminimize{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 HEREint main(void) {    Farmville ___test;    ___test.run_test(-1);//  ___test.test_case_3();    system("pause");}// END CUT HERE
原创粉丝点击