CodeForces 1517G Starry Night Camping(网络流最小割)
CodeForces 1517G Starry Night Camping
problem
洛谷鏈接
solution
這個平行四邊形的腦洞我?真的長見識了
本題最離譜的要求就是:平行四邊形的一條邊平行于 xxx 軸。
而往往這種離譜要求就是正解的途徑。(((φ(◎ロ◎;)φ)))
首先不觀察也能知道,中心點的上下必須選一個,左右必須選一個,這樣就確定了三個點。
最后一個點在上下和左右選出來后也就有了選擇限制。
這個選擇限制就是不能讓選的左右點與中心點的邊成為對角線(這種斜著的平行四邊形是被允許存在的)。
再看,還要求中心點的坐標都是偶數,我們用 O 表示奇數,E 表示偶數。
那么中心點就是 (E,E),左右點都是 (E,O),上下點都是 (O,E),剩下的一個點都是 (O,O)。
換言之,平行四邊形的四個頂點一定是由上面四類各出一個點構成的。
我們用路徑來刻畫平行四邊形的邊。
發現不合法的平行四邊形都可以被表示為 (O,O)→(O,E)→(E,E)→(E,O)(O,O)\rightarrow(O,E)\rightarrow (E,E)\rightarrow (E,O)(O,O)→(O,E)→(E,E)→(E,O),一條邊連接的兩個點的距離恰好為 111。
這說明,如果將點按橫縱坐標分成四大類,最后是不能出現長度為 444 的鏈的。
而這四類之間的邊是唯一的,定向的。
可以用拆點+網絡流。把一個坐標點拆成入點和出點,再建一個超級源點和超級匯點。
入點和出點之間就是坐標點的刪除代價,其余邊容量無窮即可。
最后是不能讓 S?TS-TS?T 之間存在流量的,也就是要把 S/TS/TS/T 割開,即最小割問題。
code
#include <bits/stdc++.h> using namespace std; #define inf 1e18 #define int long long #define maxn 2005 queue < int > q; int s, t, cnt = -1; int dep[maxn], head[maxn], cur[maxn]; struct node { int to, nxt, flow; }E[maxn << 4];void addedge( int u, int v, int w ) {E[++ cnt] = { v, head[u], w };head[u] = cnt;E[++ cnt] = { u, head[v], 0 };head[v] = cnt; }bool bfs() {memset( dep, 0, sizeof( dep ) );memcpy( cur, head, sizeof( head ) );q.push( s ), dep[s] = 1;while( ! q.empty() ) {int u = q.front(); q.pop();for( int i = head[u];~ i;i = E[i].nxt ) {int v = E[i].to;if( ! dep[v] and E[i].flow > 0 ) {dep[v] = dep[u] + 1;q.push( v );}}}return dep[t]; }int dfs( int u, int cap ) {if( ! cap or u == t ) return cap;int flow = 0;for( int i = cur[u];~ i;i = E[i].nxt ) {cur[u] = i; int v = E[i].to;if( dep[v] == dep[u] + 1 and E[i].flow > 0 ) {int w = dfs( v, min( cap, E[i].flow ) );E[i ^ 1].flow += w;E[i].flow -= w;flow += w;cap -= w;if( ! cap ) break;}}return flow; }int dinic() {int ans = 0;while( bfs() ) ans += dfs( s, inf );return ans; }int n; int x[maxn], y[maxn], w[maxn], type[maxn];signed main() {memset( head, -1, sizeof( head ) );scanf( "%lld", &n );int ans = 0;s = 1, t = n + 1 << 1;for( int i = 1;i <= n;i ++ ) {scanf( "%lld %lld %lld", &x[i], &y[i], &w[i] );if( (x[i] & 1) and (y[i] & 1) ) type[i] = 1;if( (x[i] & 1) and !(y[i] & 1) ) type[i] = 2;if( !(x[i] & 1) and !(y[i] & 1) ) type[i] = 3;if( !(x[i] & 1) and (y[i] & 1) ) type[i] = 4;ans += w[i];}for( int i = 1;i <= n;i ++ ) addedge( i << 1, i << 1 | 1, w[i] );for( int i = 1;i <= n;i ++ ) if( type[i] == 1 ) addedge( s, i << 1, inf );for( int k = 1;k <= 3;k ++ )for( int i = 1;i <= n;i ++ )if( type[i] == k )for( int j = 1;j <= n;j ++ )if( type[j] == k + 1 )if( fabs( x[i] - x[j] ) + fabs( y[i] - y[j] ) == 1 )addedge( i << 1 | 1, j << 1, inf );for( int i = 1;i <= n;i ++ ) if( type[i] == 4 ) addedge( i << 1 | 1, t, inf );printf( "%lld\n", ans - dinic() );return 0; }總結
以上是生活随笔為你收集整理的CodeForces 1517G Starry Night Camping(网络流最小割)的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 后疫情时代 金融行业数字化转型解题
 - 下一篇: CodeForces 901D Weig