日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Codeforces Gym101518H:No Smoking, Please(最小割)

發布時間:2025/3/15 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Codeforces Gym101518H:No Smoking, Please(最小割) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接

題意

給出一個n*m的酒店,每個點是一個房間,要將這個酒店的房間劃分成為兩塊(一塊無煙區,一塊吸煙區),相鄰的兩個房間之間有一條帶權邊,權值代表空氣鎖的面積,如果把這條邊給去掉,那么需要花費(空氣鎖的面積+開一個窗口傳食物)*1000元。問需要的最少花費是多少。要注意如果面積為0,則這條邊不能劃分

思路

全場做的人不多,主要看題意比較難,看懂題意就會發現是裸的最小割,但是有個面積為0的坑點。這里的邊需要開的比較大,考慮到每次增加兩個點,就會使邊增加三條(不知道這樣想對不對),于是就開兩倍(還有兩倍雙向邊)。

#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int, int> pii; const int INF = 0x3f3f3f3f; const int M = 1e3 + 11; const int N = 1e6 + 11; struct Edge {int u, v, nxt, cap; } edge[N*4]; int head[N], tot, id[M][M]; int cur[N], gap[N], dis[N], pre[N]; queue<int> que;void Add(int u, int v, int cap) {edge[tot] = (Edge) { u, v, head[u], cap }; head[u] = tot++;edge[tot] = (Edge) { v, u, head[v], cap }; head[v] = tot++; }void BFS(int T) {while(!que.empty()) que.pop();memset(dis, INF, sizeof(dis));memset(gap, 0, sizeof(gap));gap[0] = 1; dis[T] = 0;que.push(T);while(!que.empty()) {int u = que.front(); que.pop();for(int i = head[u]; ~i; i = edge[i].nxt) {int v = edge[i].v;if(dis[v] != INF) continue;dis[v] = dis[u] + 1;gap[dis[v]]++;que.push(v);}} }int ISAP(int S, int T, int n) {BFS(T);memcpy(cur, head, sizeof(cur));int i, flow, u = pre[S] = S, index, ans = 0;while(dis[S] < n) {if(u == T) {flow = INF, index = u;for(u = S; u != T; u = edge[cur[u]].v)if(edge[cur[u]].cap < flow) flow = edge[cur[u]].cap, index = u;for(u = S; u != T; u = edge[cur[u]].v)edge[cur[u]].cap -= flow, edge[cur[u]^1].cap += flow;u = index, ans += flow;}for(i = cur[u]; ~i; i = edge[i].nxt)if(dis[edge[i].v] == dis[u] - 1 && edge[i].cap) break;if(~i) {pre[edge[i].v] = u; cur[u] = i; u = edge[i].v;} else {if(--gap[dis[u]] == 0) break;int md = n + 1;for(i = head[u]; ~i; i = edge[i].nxt)if(edge[i].cap && dis[edge[i].v] < md) md = dis[edge[i].v], cur[u] = i;gap[dis[u] = md + 1]++;u = pre[u];}} return ans; }int main() {int t; scanf("%d", &t);while(t--) {memset(head, -1, sizeof(head));tot = 0;int n, m, sx, sy, ex, ey;scanf("%d%d", &n, &m);scanf("%d%d%d%d", &sx, &sy, &ex, &ey);int cnt = 0;for(int i = 0; i < n; i++)for(int j = 0; j < m; j++) id[i][j] = ++cnt;for(int i = 0; i < n; i++) {for(int j = 0; j < m - 1; j++) {int cap; scanf("%d", &cap);if(cap) Add(id[i][j], id[i][j+1], cap + 1);}}for(int i = 0; i < n - 1; i++) {for(int j = 0; j < m; j++) {int cap; scanf("%d", &cap);if(cap) Add(id[i][j], id[i+1][j], cap + 1);}}printf("%d\n", ISAP(id[sx][sy], id[ex][ey], n * m) * 1000);} return 0; }

轉載于:https://www.cnblogs.com/fightfordream/p/7636624.html

總結

以上是生活随笔為你收集整理的Codeforces Gym101518H:No Smoking, Please(最小割)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。