[最小割]SRM 590 div 1 1000pts FoxAndCity

来源:互联网 发布:淘宝 深圳远望数码手机 编辑:程序博客网 时间:2024/05/29 03:28

Solution

类似于这个题。
这里写图片描述
F表示falseT表示true
建出这些点后,原图中的边(u,v)就相当于限制|dudv|1
还有d1=0di0,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 HEREint main(void) {    FoxAndCity ___test;    ___test.run_test(-1);    system("pause");}// END CUT HERE
原创粉丝点击