1. 程式人生 > >P2598 [ZJOI2009]狼和羊的故事(最小割)

P2598 [ZJOI2009]狼和羊的故事(最小割)

rake 並且 輸入輸出 ora bsp 題目 ros algorithm 整數

P2598 [ZJOI2009]狼和羊的故事

題目描述

“狼愛上羊啊愛的瘋狂,誰讓他們真愛了一場;狼愛上羊啊並不荒唐,他們說有愛就有方向......” Orez聽到這首歌,心想:狼和羊如此和諧,為什麽不嘗試羊狼合養呢?說幹就幹! Orez的羊狼圈可以看作一個n*m個矩陣格子,這個矩陣的邊緣已經裝上了籬笆。可是Drake很快發現狼再怎麽也是狼,它們總是對羊垂涎三尺,那首歌只不過是一個動人的傳說而已。所以Orez決定在羊狼圈中再加入一些籬笆,還是要將羊狼分開來養。 通過仔細觀察,Orez發現狼和羊都有屬於自己領地,若狼和羊們不能呆在自己的領地,那它們就會變得非常暴躁,不利於他們的成長。 Orez想要添加籬笆的盡可能的短。當然這個籬笆首先得保證不能改變狼羊的所屬領地,再就是籬笆必須修築完整,也就是說必須修建在單位格子的邊界上並且不能只修建一部分。

輸入輸出格式

輸入格式:

文件的第一行包含兩個整數n和m。接下來n行每行m個整數,1表示該格子屬於狼的領地,2表示屬於羊的領地,0表示該格子不是任何一只動物的領地。

輸出格式:

文件中僅包含一個整數ans,代表籬笆的最短長度。

輸入輸出樣例

輸入樣例#1: 復制
2 2
2 2 
1 1 
輸出樣例#1: 復制
2

說明

數據範圍

10%的數據 n,m≤3

30%的數據 n,m≤20

100%的數據 n,m≤100

分析

最小割,使得狼與羊不連通。

註意建圖:S向狼連INF的邊,狼連羊連1的邊,羊連T連INF的邊。狼向空地,羊向空連1的邊,空地與空地連1的邊。

code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define id(x,y) (x-1)*m+y
 5 
 6 using namespace std;
 7 
 8 const int INF = 1e9;
 9 const int N = 10010;
10 
11 struct Edge{
12     int to,nxt,c;
13 }e[100100];
14 int head[N],dis[N],cur[N],q[100100],mp[110
][110]; 15 int L,R,tot = 1,S,T; 16 int dx[4] = {0,0,1,-1},dy[4] = {1,-1,0,0}; 17 18 inline char nc() { 19 static char buf[100000],*p1 = buf,*p2 = buf; 20 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 21 } 22 inline int read() { 23 int x = 0,f = 1;char ch = nc(); 24 for (; ch<0||ch>9; ch = nc()) if (ch==-) f = -1; 25 for (; ch>=0&&ch<=9; ch = nc()) x = x * 10 + ch - 0; 26 return x * f; 27 } 28 inline void add_edge(int u,int v,int w) { 29 e[++tot].to = v,e[tot].c = w,e[tot].nxt = head[u],head[u] = tot; 30 e[++tot].to = u,e[tot].c = 0,e[tot].nxt = head[v],head[v] = tot; 31 } 32 bool bfs() { 33 for (int i=0; i<=T; ++i) { 34 cur[i] = head[i];dis[i] = -1; 35 } 36 L = 1;R = 0; 37 q[++R] = S;dis[S] = 0; 38 while (L <= R) { 39 int u = q[L++]; 40 for (int i=head[u]; i; i=e[i].nxt) { 41 int v = e[i].to,c = e[i].c; 42 if (dis[v]==-1 && c>0) { 43 dis[v] = dis[u] + 1; 44 q[++R] = v; 45 if (v==T) return true; 46 } 47 } 48 } 49 return false; 50 } 51 int dfs(int u,int flow) { 52 if (u==T) return flow; 53 int used = 0; 54 for (int &i=cur[u]; i; i=e[i].nxt) { 55 int v = e[i].to,c = e[i].c; 56 if (dis[v]==dis[u]+1 && c>0) { 57 int tmp = dfs(v,min(c,flow-used)); 58 if (tmp > 0) { 59 e[i].c -= tmp;e[i^1].c += tmp; 60 used += tmp; 61 if (used==flow) break; 62 } 63 } 64 } 65 if (used!=flow) dis[u] = -1; 66 return used; 67 } 68 inline int dinic() { 69 int ans = 0; 70 while (bfs()) ans += dfs(S,INF); 71 return ans; 72 } 73 int main() { 74 int n = read(),m = read(); 75 S = 0;T = n*m+1; 76 for (int i=1; i<=n; ++i) 77 for (int j=1; j<=m; ++j) 78 mp[i][j] = read(); 79 for (int i=1; i<=n; ++i) 80 for (int j=1; j<=m; ++j) { 81 if (mp[i][j]==2) {add_edge(id(i,j),T,INF);continue;} 82 if (mp[i][j]==1) add_edge(S,id(i,j),INF); 83 for (int k=0; k<4; ++k) { 84 int x = i + dx[k],y = j + dy[k]; 85 if (x>0 && x<=n && y>0 && y<=m && mp[x][y]!=1) 86 add_edge(id(i,j),id(x,y),1); 87 } 88 } 89 printf("%d",dinic()); 90 return 0; 91 }

P2598 [ZJOI2009]狼和羊的故事(最小割)