题目描述
“狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非常暴躁,不利于他们的成长。 Orez想要添加篱笆的尽可能的短。当然这个篱笆首先得保证不能改变狼羊的所属领地,再就是篱笆必须修筑完整,也就是说必须修建在单位格子的边界上并且不能只修建一部分。
输入输出格式
输入格式:
文件的第一行包含两个整数n和m。接下来n行每行m个整数,1表示该格子属于狼的领地,2表示属于羊的领地,0表示该格子不是任何一只动物的领地。
输出格式:
文件中仅包含一个整数ans,代表篱笆的最短长度。
输入输出样例
说明
数据范围
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 }