[最小割]SRM 590 div-1 Hard FoxAndCity

Solution

类似于这个题
这里写图片描述
F 表示false T 表示true
建出这些点后,原图中的边 (u,v) 就相当于限制 |dudv|1
还有 d1=0 di0,i=2..n 。只要保证相应的边不能被割到就好了。

// BEGIN CUT HERE

// END CUT HERE
#line 5 "FoxAndCity.cpp"
#include <bits/stdc++.h>
using namespace std;

const int N = 50;
const int INF = 1 << 29;

struct edge {
    int to, next, flow;
    edge(int t = 0, int n = 0, int f = 0):to(t), next(n), flow(f) {}
};
edge G[N * N * N * 10];
int head[N * N], cur[N * N];
int dis[N * N], vis[N * N];
int id[N][N];
int c[N];
int Gcnt, n, clc, S, T, cnt;
queue<int> Q;

inline void AddEdge(int from, int to, int flow) {
    G[++Gcnt] = edge(to, head[from], flow); head[from] = Gcnt;
    G[++Gcnt] = edge(from, head[to], 0); head[to] = Gcnt;
}
inline void Init(void) {
    Gcnt = 1; cnt = 0; memset(head, 0, sizeof head);
}
inline bool bfs(int S, int T) {
    Q.push(S); dis[S] = 0; vis[S] = ++clc;
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        for (int i = head[u]; i; i = G[i].next) {
            edge &e = G[i];
            if (e.flow && vis[e.to] != clc) {
                dis[e.to] = dis[u] + 1;
                vis[e.to] = clc; Q.push(e.to);
            }
        }
    }
    return vis[T] == clc;
}
inline int dfs(int u, int a) {
    if (u == T || !a) return a;
    int f, flow = 0;
    for (int &i = cur[u]; i; i = G[i].next) {
        edge &e = G[i];
        if (e.flow && dis[e.to] == dis[u] + 1
          && (f = dfs(e.to, min(e.flow, a))) > 0) {
            e.flow -= f; G[i ^ 1].flow += f;
            flow += f; a -= f; if (!a) break;
          }
    }
    return flow;
}
inline int MaxFlow(int S, int T) {
    int flow = 0;
    while (bfs(S, T)) {
        for (int i = 0; i <= T; i++) cur[i] = head[i];
        flow += dfs(S, INF);
    }
    return flow;
}
inline int sqr(int x) {
    return x * x;
}

class FoxAndCity {

public:
    int minimalCost(vector <string> linked, vector <int> want) {
        n = want.size(); Init();
        for (int i = 1; i <= n; i++) {
            c[i] = want[i - 1];
            for (int j = 0; j < n; j++)
                id[i][j] = ++cnt;
        }
        S = ++cnt; T = ++cnt;
        for (int i = 1; i <= n; i++) {
            if (i == 1) AddEdge(id[i][0], T, INF);
            else AddEdge(S, id[i][0], INF);
            AddEdge(S, id[i][0], sqr(c[i]));
            for (int j = 1; j < n; j++)
                AddEdge(id[i][j - 1], id[i][j], sqr(j - c[i]));
            AddEdge(id[i][n - 1], T, INF);
        }
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                if (i != j && linked[i - 1][j - 1] == 'Y')
                    for (int k = 1; k < n; k++)
                        AddEdge(id[i][k], id[j][k - 1], INF);
        return MaxFlow(S, T);
    }

// 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(); if ((Case == -1) || (Case == 6)) test_case_6(); }
    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[] = {"NYN",
 "YNY",
 "NYN"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0, 1, 1}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 0; verify_case(0, Arg2, minimalCost(Arg0, Arg1)); }
    void test_case_1() { string Arr0[] = {"NYNN",
 "YNYN",
 "NYNY",
 "NNYN"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0, 3, 3, 3}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 5; verify_case(1, Arg2, minimalCost(Arg0, Arg1)); }
    void test_case_2() { string Arr0[] = {"NYNNNY",
 "YNYNNN",
 "NYNYNN",
 "NNYNYN",
 "NNNYNY",
 "YNNNYN"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0, 2, 2, 2, 2, 2}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 2; verify_case(2, Arg2, minimalCost(Arg0, Arg1)); }
    void test_case_3() { string Arr0[] = {"NYY","YNN","YNN"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0,0,0}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 2; verify_case(3, Arg2, minimalCost(Arg0, Arg1)); }
    void test_case_4() { string Arr0[] = {"NYNNNN",
 "YNYNNN",
 "NYNYYY",
 "NNYNYY",
 "NNYYNY",
 "NNYYYN"}
; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0, 1, 2, 3, 0, 3}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 3; verify_case(4, Arg2, minimalCost(Arg0, Arg1)); }
    void test_case_5() { string Arr0[] = {"NYNNNN",
 "YNYNNN",
 "NYNYYY",
 "NNYNYY",
 "NNYYNY",
 "NNYYYN"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0, 1, 2, 4, 0, 4}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 6; verify_case(5, Arg2, minimalCost(Arg0, Arg1)); }
    void test_case_6() { string Arr0[] = {"NYNYYYYYYYY","YNYNNYYNYYY","NYNNNYYNYYN","YNNNYYYYYYY","YNNYNYYYNYY","YYYYYNNYYNY","YYYYYNNNYYY","YNNYYYNNNYY","YYYYNYYNNNY","YYYYYNYYNNY","YYNYYYYYYYN"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0,1,2,0,0,5,1,3,0,2,3}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 28; verify_case(6, Arg2, minimalCost(Arg0, Arg1)); }

// END CUT HERE


};

// BEGIN CUT HERE
int main(void) {
    FoxAndCity ___test;
    ___test.run_test(-1);
    system("pause");
}
// END CUT HERE
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值