1. 程式人生 > >【清華集訓 2017】無限之環(費用流)

【清華集訓 2017】無限之環(費用流)

題目連結

題解

費用流神題。

對於每一個方格延伸出去的每一根水管,有且僅有一個其他方格延伸出的水管與之相連,這樣就不會漏水。即:每根水管的容量為1,且必須滿流。

然而即使產生了最優情況,整個管網也不一定是一整個聯通塊,而可能被分成若干塊。因此,我們要對每個格點染色,相鄰的兩個格點,一個連源點,一個連匯點,就可以強制使每兩個相鄰的方格上都產生流量了。

旋轉所花的步數即是費用。將一個方格拆成5個點(上下左右中),中間點連上源or匯點,並根據水管情況向四周連容量1,費用0的邊。四周視作接觸點,與對應相鄰的另一個接觸點連容量1,費用0的邊。接下來,對於每一種形狀的格子,分類討論。

  • 射線型:讓左、下、右接觸點直接連線上接觸點。左,右連上去,只轉一次,所以費用為1。下面連上去費用就是2
  • 直角型:旋轉一次後,發現上下切換or左右切換。那麼上與下、左與右之間各建一條容量為1,費用為1的邊。
  • 丁字型:與第一種情況類似,左、上、右接觸點直接連線下接觸點。左,右連下去,只轉一次,所以費用為1。上面連下去費用就是2

至此,構圖已經完成,接下來只要套上模版即可。

程式碼

//「Luogu4003」Infinity Loop
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue> using namespace std; #define c(k) k + (sum << 2) #define u(k) k + turn * sum #define r(k) k + ((turn + 1) & 3) * sum #define d(k) k + ((turn + 2) & 3) * sum #define l(k) k + ((turn + 3) & 3) * sum const int maxn = 100005; const int maxm = 2000005; const int inf = 1000000000; bool
vis[maxn]; int n, m, cnt, sum, src, snk, ans, dis[maxn]; int tot, ter[maxm], len[maxm], wei[maxm], nxt[maxm], lnk[maxn]; inline void add(int u, int v, int w0, int w1) { ter[tot] = v; len[tot] = w0; wei[tot] = w1; nxt[tot] = lnk[u]; lnk[u] = tot++; // printf("(%d, %d): (%d, %d);\n", u, v, w0, w1); } void addedge(int u, int v, int w0, int w1, int type) { if (type) { swap(u, v); } add(u, v, w0, w1); add(v, u, 0, -w1); } bool spfa(int s, int t) { queue<int> que; que.push(s); memset(dis, 0x3f, sizeof(dis)); dis[s] = 0, vis[s] = 1; int w0, w1; for (int u, v; !que.empty(); ) { u = que.front(); que.pop(); vis[u] = 0; for (int i = lnk[u]; ~i; i = nxt[i]) { v = ter[i], w0 = len[i], w1 = wei[i]; if (w0 && dis[v] > dis[u] + w1) { dis[v] = dis[u] + w1; if (!vis[v]) { vis[v] = 1; que.push(v); } } } } return dis[t] < inf; } int find(int u, int lft) { if (u == snk) { return lft; } vis[u] = 1; int w0, w1, tmp, res = 0; for (int v, i = lnk[u]; ~i && res < lft; i = nxt[i]) { v = ter[i], w0 = len[i], w1 = wei[i]; if (w0 && !vis[v] && dis[u] + w1 == dis[v]) { tmp = find(v, min(lft - res, w0)); if (tmp) { ans += tmp * w1; len[i] -= tmp; len[i ^ 1] += tmp; res += tmp; } } } vis[u] = 0; return res; } int mcmf() { int tmp, res = 0; while (spfa(src, snk)) { tmp = find(src, inf); while (tmp) { res += tmp; tmp = find(src, inf); } } return res; } int main() { memset(lnk, -1, sizeof(lnk)); scanf("%d %d", &n, &m); sum = n * m; src = 0; snk = sum * 5 + 1; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { int turn = 0, shape; int type = (i ^ j) & 1; int id = (i - 1) * m + j; scanf("%d", &shape); if (type) { addedge(src, c(id), inf, 0, 0); } else { addedge(c(id), snk, inf, 0, 0); } if (i > 1) { addedge(d(id - m), u(id), 1, 0, type); } if (j > 1) { addedge(r(id - 1), l(id), 1, 0, type); } if (shape & 1) { addedge(u(id), c(id), 1, 0, type); cnt++; } if (shape & 2) { addedge(r(id), c(id), 1, 0, type); cnt++; } if (shape & 4) { addedge(d(id), c(id), 1, 0, type); cnt++; } if (shape & 8) { addedge(l(id), c(id), 1, 0, type); cnt++; } switch (shape) { case 8: turn++; case 4: turn++; case 2: turn++; case 1: addedge(r(id), u(id), 1, 1, type); addedge(d(id), u(id), 1, 2, type); addedge(l(id), u(id), 1, 1, type); break; case 9: turn++; case 12: turn++; case 6: turn++; case 3: addedge(d(id), u(id), 1, 1, type); addedge(l(id), r(id), 1, 1, type); break; case 13: turn++; case 14: turn++; case 7: turn++; case 11: addedge(d(id), l(id), 1, 1, type); addedge(d(id), u(id), 1, 2, type); addedge(d(id), r(id), 1, 1, type); break; } } } cnt >>= 1; if (mcmf() == cnt) { printf("%d\n", ans); } else { puts("-1"); } return 0; }

相關推薦

清華集訓 2017無限費用

題目連結 題解 費用流神題。 對於每一個方格延伸出去的每一根水管,有且僅有一個其他方格延伸出的水管與之相連,這樣就不會漏水。即:每根水管的容量為11,且必須滿流。 然而即使產生了最優情況,整個管網也不一定是一整個聯通塊,而可能被分成若干塊。因此,

BZOJ5120 無限費用

  方案合法相當於要求介面之間配對,黑白染色一波,考慮網路流。有一個很奇怪的限制是不能旋轉直線型水管,考慮非直線型水管有什麼特殊性,可以發現其介面都是連續的。那麼對於旋轉水管,可以看做是把順/逆時針方向上最後的介面提到最前。於是用四個點表示某格子的四個方向,以上述方式只移動一次就能相互轉換的方向之間連費用1的

LOJ2321清華集訓 2017無限

【題目連結】 【思路要點】 先說這道題的正解: 將棋盤看做一張二分圖,每一條邊拆成兩個點,分別屬於二分圖的一邊。 我們需要做一件類似於匹配的事情,同一條邊的兩側或是都沒有管道,或是都有管道。 通過合適的建邊我們能夠用最小費用最大流來解決本題。 時間複雜度

清華集訓 2017無限

無限之WA https://www.luogu.org/problemnew/show/P4003 本題如果知道是網路流的話,其實建圖不算特別神奇,但是比較麻煩。 資料範圍過大,插頭dp不能處理,而且是一個網格圖,考慮網路流。 先看是不是二分圖? 每個格子只會和相鄰四個格子發生關係 所以,黑白染色

LOJ2321「清華集訓 2017無限

無限之環 題目描述 曾經有一款流行的遊戲,叫做InfinityLoopInfinityLoop,先來簡單的介紹一下這個遊戲: 遊戲在一個 n×mn×m的網格狀棋盤上進行,其中有些小方格中會有水管,水管可能在方格某些方向的邊界的中點有介面,所

uoj#275. 清華集訓2016組合數問題數位dp

傳送門 假設有\(k|{n\choose m}\),因為\(n!\)中質因子\(k\)的次數為\(S(n)=\left\lfloor\frac{n}{k}\right\rfloor+\left\lfloor\frac{n}{k^2}\right\rfloor+...\),而\(m!\)和\((n-m)!\)

洛谷 P4134 [BJOI2012]連連看費用

org const set pop main %d from += spa 題目鏈接 首先是可以\(O(n^2)\)枚舉出所有符合要求的點對的,然後考慮建圖。 還是拆點把每個點拆成入點和出點,源點連入點,出點連匯點,流量都是1,費用都是0。 然後對於沒對符合要求的\((x,

洛谷 P4016 負載平衡問題費用

ons esp define code ace sca ring 個數 pre 題目鏈接 環形均分紙牌,既然是網絡流23題的那就用網絡流做把。 套路拆點。 供需平衡。 源點向大於平均數的點的入點連流量為這個數減去平均數的差,費用為0的邊,表示需要移走這麽多。 小於平均數的點

UOJ#340清華集訓2017小 Y 和恐怖的奴隸主矩陣快速冪,動態規劃

【UOJ#340】【清華集訓2017】小 Y 和恐怖的奴隸主(矩陣快速冪,動態規劃) 題面 UOJ 洛谷 題解 考慮如何暴力\(dp\)。 設\(f[i][a][b][c]\)表示當前到了第\(i\)次攻擊,還剩下的\(1,2,3\)血的奴隸主個數為\(a,b,c\)的概率,每次考慮打到了哪裡,做一個

網絡24題數字梯形問題費用最大權不相交路徑

output 提示 正整數 cti 移動 block 完全 amp 方向 1913 數字梯形問題 時間限制: 2 s 空間限制: 256000 KB 題目等級 : 大師 Master

網絡24題深海機器人問題費用

排列 bold 起點 給定 text 限定 科學 cnblogs 必須 1917 深海機器人問題 題目描述 Description 深海資源考察探險隊的潛艇將到達深海的海底進行科學考察。潛艇內有多個深海機器

網絡24題航空線路問題費用

cnblogs memset stream false div ems 最大 網絡流 har 【網絡流24題】航空線路問題(費用流) 題面 Cogs數據有誤,提供洛谷題面 題解 這題和原來做過的一道題周遊加拿大是一模一樣的 所以,這題DP+記錄方案應該也是可行的 來考慮網絡

Bzoj1927星際競速費用

read lin logs esp clu blog using tdi ++ Description 題意:給定n個點m條邊的無向圖,只能從編號小的到編號大的,且要求經過所有點剛好一次,而且可以從任意點瞬移到i號點並花費代價Ai,求最小代價。 n<=800,m<

2018.10.22網路24題洛谷P2770LOJ6122航空路線問題費用

洛谷傳送門 解析: 調了半天最後發現費用流部分一個小細節跪了。。。 心態爆炸。。。問題不大 思路: 首先我們直接找出兩條沒有重複節點的路徑,一條正著輸出一條倒著輸出就行了。 找的話考慮網路流。我們將每個點拆點成兩個ai,bia_i,b_iai​,bi​,為保

網路24題火星探險問題費用

題面 題解 如果不考慮標本的採集 那麼,很容易的 直接相鄰點連邊就行了 現在,因為要考慮標本數最多 所以每個點要額外考慮一個標本 但是標本又只能採集一次 所以,拆點,標本就額外的連一條容量1費用1的邊, 表示可以採集一次, 因為採集過之後

LOJ2330清華集訓 2017」榕樹

【題目連結】 點選開啟連結 【思路要點】 首先,樹是二分圖,只有一側的點可能成為心。 維護每一棵子樹會產生的向下推動的次數可能的最大值

loj#2330. 「清華集訓 2017」榕樹樹形dp

傳送門 解題思路: 先考慮根是否可行,即步數是否能抵消完。 考慮w[x]w[x]表示xx的子樹內最少的消剩下的點數。 觀察發現,最難消的肯定是sizesize最大的兒子,設為 yy ,而且如果

LOJ#2330. 「清華集訓 2017」榕樹心 -樹形dp

題解 先考慮根的情況(Subtask3Subtask3)。 根的每個兒子及其構成的子樹之間可以互相抵消。 設rem[i]rem[i]表示以ii為根的子樹最少的不能互相抵消的點數。 那

清華集訓2017模擬Catalan

Description 求Cnmod3814697265625(518)其中Cn為卡特蘭數第n項 n<=10^18,T<=10 Solution 這麼大的組合數取模啊。。。。以前真沒見過 首先我們知道Ans=Cn2nn+1 根據套路我們只

清華集訓2017模擬12.10迴文串迴文樹+樹鏈剖分

Description: NYG 很喜歡研究迴文串問題,有一天他想到了這樣一個問題: 給出一個字串 S,現在有 4 種操作: • addl c :在當前字串的左端加入字元 c; • addr c :在當前字串的右端加入字元 c; • transl l