Topcoder SRM590 Fox And City
Problem Statement |
|
There is a country with n cities, numbered 0 through n-1. City 0 is the capital. The road network in the country forms an undirected connected graph. In other words: Some pairs of cities are connected by bidirectional roads. For every city there is at least one sequence of consecutive roads that leads from the city to the capital. (Whenever two roads need to cross outside of a city, the crossing is done using a bridge, so there are no intersections outside of the cities.) You are given a String[] linked |
題目大意:給定n個點的無向圖,邊權均為1,每個點有一個屬性wi,現在可以在圖中任意加邊,記加邊後每個點到1號點的距離為di,最小化Σ(wi - di)^2.
樣例:
Sample Input
3
NYN
YNY
NYN
0 1 1
4
NYNN
YNYN
NYNY
NNYN
0 3 3 3
6
NYNNNY
YNYNNN
NYNYNN
NNYNYN
NNNYNY
YNNNYN
0 2 2 2 2 2
3
NYY
YNN
YNN
0 0 0
6
NYNNNN
YNYNNN
NYNYYY
NNYNYY
NNYYNY
NNYYYN
0 1 2 3 0 3
6
NYNNNN
YNYNNN
NYNYYY
NNYNYY
NNYYNY
NNYYYN
0 1 2 4 0 4
11
NYNYYYYYYYY
YNYNNYYNYYY
NYNNNYYNYYN
YNNNYYYYYYY
YNNYNYYYNYY
YYYYYNNYYNY
YYYYYNNNYYY
YNNYYYNNNYY
YYYYNYYNNNY
YYYYYNYYNNY
YYNYYYYYYYN
0 1 2 0 0 5 1 3 0 2 3
Sample Output
0
5
2
3
6
28
分析:綜合了許多知識的好題.
題目說可以任意加邊,那麽是不是就意味著每個點的最短路都是任意的呢? 顯然不是的,考慮確定每個點的最短路有什麽限制.
首先,d1 = 0. 然後對於任意有邊的一對點(i,j),|di - dj| ≤ 1. 現在要求滿足上述限制的最值.
這其實就是個離散變量模型,和bzoj3144類似. 先拆點,S向i號點拆出的0號點連容量為inf的邊,i號點拆出的n-1號點向T連容量為inf的邊. i號點拆出的k號點向k+1號點連容量為(a[i] - k - 1) ^ 2的邊.
對於有限制的點對(i,j),i拆出的第k個點向j拆出的第k-1個點連容量為inf的邊,j連i也同樣如此.
還沒完.必須保證d1 = 0.那麽1拆出的第k個點向第k+1個點的邊就不能被割. 將其容量變成inf就好了. 但是這樣會存在一個問題:ST總是連通的. 因為S到T總是可以經過1號點拆出的點,這條路徑上的每條邊的容量都是inf,割不掉.
怎麽解決呢?去掉S與1號點拆出的第一個點的連邊就好了.
不斷調整,滿足最小割的要求,同時使得答案合理,這是最小割模型建圖的一般分析方法.
同時這道題融合了最短路問題的一些技巧,例如hdu5385,每個點到源點的最短路都和與它相連的點的最短路有關.
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 300010,inf = 0x7fffffff; int n,a[50],id[50][50],cnt,head[maxn],to[maxn],nextt[maxn],w[maxn],tot = 2; int d[maxn],S,T,ans; char s[110][110]; void add(int x,int y,int z) { w[tot] = z; to[tot] = y; nextt[tot] = head[x]; head[x] = tot++; w[tot] = 0; to[tot] = x; nextt[tot] = head[y]; head[y] = tot++; } bool bfs() { memset(d,-1,sizeof(d)); d[S] = 0; queue <int> q; q.push(S); while (!q.empty()) { int u = q.front(); q.pop(); if (u == T) return true; for (int i = head[u];i;i = nextt[i]) { int v = to[i]; if (w[i] && d[v] == -1) { d[v] = d[u] + 1; q.push(v); } } } return false; } int dfs(int u,int f) { if (u == T) return f; int res = 0; for (int i = head[u];i;i = nextt[i]) { int v = to[i]; if (w[i] && d[v] == d[u] + 1) { int temp = dfs(v,min(f - res,w[i])); w[i] -= temp; w[i ^ 1] += temp; res += temp; if (res == f) return res; } } if (!res) d[u] = -1; return res; } void dinic() { while(bfs()) ans += dfs(S,inf); } int main() { scanf("%d",&n); for (int i = 1; i <= n; i++) scanf("%s",s[i] + 1); for (int k = 0; k <= n - 1; k++) for (int i = 1; i <= n; i++) id[i][k] = ++cnt; S = cnt + 1; T = S + 1; add(id[1][n - 1],T,inf); for (int i = 2; i <= n; i++) add(S,id[i][0],inf),add(id[i][n - 1],T,inf); for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) { if (s[i][j] == ‘Y‘) { for (int k = 1; k <= n - 1; k++) add(id[i][k],id[j][k - 1],inf); } } for (int i = 1; i <= n; i++) { int x; scanf("%d",&x); for (int j = 0; j <= n - 2; j++) add(id[i][j],id[i][j + 1],(i == 1 ? inf : (x - j - 1) * (x - j - 1))); } dinic(); printf("%d\n",ans); return 0; }
Topcoder SRM590 Fox And City