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

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 HERE
int main(void) {
    Farmville ___test;
    ___test.run_test(-1);
//  ___test.test_case_3();
    system("pause");
}
// END CUT HERE
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值