SRM590Hard

题意

\(n\) 个点的连通无向图和 \(a_0,\ a_1,\ ...,\ a_{n\ -\ 1}\)
问添加一些(可以不加)边后 \(\sum_{i\ =\ 0}^{n\ -\ 1}\ (dist_{0,\ i}\ -\ a_i)^2\) 最小是多少。

\(1\ \leq\ n\ \leq\ 40\)

做法1

考虑网络流。
合法的 \(dist_{0,\ i}\) 数组应满足:
1.\(dist_{0,\ 0}\ =\ 0\)
2.\(dist_{0,\ i}\ >\ 0,\ (1\ \leq\ i)\)
3.\(\forall\ (u,\ v)\ \in\ E,\ |dist_{0,\ u}\ -\ dist_{0,\ v}|\ \leq\ 1\),其中 \(E\) 是输入的边集。
于是可以将一个点 \(u\) 拆成 \((u,\ 0),\ (u,\ 1),\ ...,\ (u,\ n\ -\ 1)\),相邻两个连一条流量为代价的边,并连 \(S,\ (u,\ 0)\) 流量为 \(\infty\)\((u,\ n\ -\ 1),\ T\) 流量为代价。
处理 \(3.\) 的限制时将 \((u,\ i)\)\((v,\ i\ -\ 1)\) 连边, \((v,\ i)\)\((u,\ i\ -\ 1)\) 连流量为 \(\infty\) 的边即可。最小割即为所求。

代码

#line 2 "FoxAndCity.cpp"
#include <bits/stdc++.h>

#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif

#ifdef __WIN32
#define LLFORMAT "I64"
#define Rand() ((rand() << 15) + rand())
#else
#define LLFORMAT "ll"
#define Rand() (rand())
#endif


using namespace std;

class FoxAndCity {
	public:
	int minimalCost(vector <string> linked, vector <int> want) ;
	
// 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

} ___test;

// BEGIN CUT HERE
int main() {
	int test_case;
	scanf("%d", &test_case);
	___test.run_test(test_case);
}
// END CUT HERE

//----------head----------

const int maxv = 1710, maxe = 1e6 + 10, oo = 1e9;

int n, to[maxe], nxt[maxe], cap[maxe], head[maxv], S, T, m, d[maxv], iter[maxv];

void add_edge(int u, int v, int c) { to[m] = v; nxt[m] = head[u]; cap[m] = c; head[u] = m++; return; }

void add_biedge(int u, int v, int c) { add_edge(u, v, c); add_edge(v, u, 0); return;  }

bool bfs() {
	static int q[maxv], fnt, rar;
	fnt = rar = 0; q[rar++] = S;
	memset(d, -1, sizeof(d[0]) * n); d[S] = 0;
	while(fnt != rar) {
		int u = q[fnt++];
		for (int i = head[u]; ~i; i = nxt[i]) if(cap[i] && !~d[to[i]]) d[q[rar++] = to[i]] = d[u] + 1;
	}
	return ~d[T];
}

int dfs(int u = S, int f = oo) {
	if(u == T) return f;
	int t = f;
	for (int v, &i = iter[u]; ~i; i = nxt[i]) if(cap[i] && d[v = to[i]] == d[u] + 1) {
		int F = dfs(v, min(t, cap[i]));
		t -= F;
		cap[i] -= F;
		cap[i ^ 1] += F;
		if(!t) return f;
	}
	return f - t;
}

int FoxAndCity::minimalCost(vector <string> linked, vector <int> want) {
	int N = linked.size();
	m = 0;
	S = N * N; T = S + 1; n = T + 1;
	memset(head, -1, sizeof(head[0]) * n);
	for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) if(linked[i][j] == 'Y') {
		for (int k = 1; k < N; ++k) add_biedge(i * N + k, j * N + k - 1, oo);
	}
	for (int i = 0; i < N; ++i) {
		add_biedge(S, i * N, oo);
		if(i == 0) {
			for (int k = 1; k < N; ++k) add_biedge(i * N + k - 1, i * N + k, (k == 1 ? 0 : oo));
			add_biedge(i * N + N - 1, T, oo);
		}
		else {
			for (int k = 1; k < N; ++k) add_biedge(i * N + k - 1, i * N + k, (k == 1 ? oo : (want[i] - k + 1) * (want[i] - k + 1)));
			add_biedge(i * N + N - 1, T, (want[i] - N + 1) * (want[i] - N + 1));
		}
	}
	int ans = 0;
	while(bfs()) {
		memcpy(iter, head, sizeof(iter[0]) * n);
		for (int f = dfs(); f; f = dfs()) ans += f;
	}
	return ans;
}
posted @ 2018-09-08 16:41  King_George  阅读(396)  评论(0编辑  收藏  举报