“狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向......”
Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干!
Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。
通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非常暴躁,不利于他们的成长。
Orez想要添加篱笆的尽可能的短。当然这个篱笆首先得保证不能改变狼羊的所属领地,再就是篱笆必须修筑完整,也就是说必须修建在单位格子的边界上并且不能只修建一部分。
输入数据
输入数据存放在文本文件ws.in中。
文件的第一行包含两个整数n和m。接下来n行每行m个整数,1表示该格子属于狼的领地,2表示属于羊的领地,0表示该格子不是任何一只动物的领地。
输出数据
输出数据存放在文本文件ws.out中。
文件中仅包含一个整数ans,代表篱笆的最短长度。
样例输入
2 2
2 2
1 1
样例输出
2
数据范围
10%的数据 n,m≤3
30%的数据 n,m≤20
100%的数据 n,m≤100
应该是最小割 吧 ,我是参照黄学长的做法 ,qwq ,可以去黄学长那里看一下题解吧。
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cstdio> 5 #include <queue> 6 #include <vector> 7 const int inf = 1<<30 , maxn = 10000 + 11 , N = 100 ; 8 using namespace std ; 9 int n , m , ans , head[maxn] , s , t , cnt , cur[maxn] , jv[N][N] , tot , dis[maxn]; 10 int sj[4][2] = { 0 , 1 , 0 , -1 , 1 , 0 , -1 , 0 } , sg[4] ; 11 struct id 12 { 13 int nxt , to , val ; 14 } ; 15 vector < id > edge ; 16 queue <int> Q ; 17 18 inline void Init( ) 19 { 20 freopen( "ws.in" , "r" , stdin ) ; 21 freopen( "ws.out" , "w" , stdout ) ; 22 } 23 24 25 int read( ) 26 { 27 char ch = getchar( ) ; int k = 1 , ret = 0 ; 28 while( ch < '0' || ch > '9' ) { if( ch == '-' ) k = -1 ; ch = getchar( ) ; } 29 while( ch >= '0' && ch <= '9' ) ret = ret * 10 + ch - '0' , ch = getchar( ) ; 30 return ret * k ; 31 } 32 33 34 void add( int u , int v , int vi ) 35 { 36 id a ; 37 a.nxt = head[u] , a.to = v ; 38 a.val = vi ; edge.push_back( a ) ; 39 head[u] = edge.size( ) - 1; 40 } 41 42 43 void link( int x , int y , int tote ) 44 { 45 if( jv[x][y] == 2 ) 46 { 47 add( 0 , tote , inf ) ; 48 add( tote , 0 , 0 ) ; 49 } 50 int xx , yy , now ; 51 for( int i = 0 ; i < 4 ; ++i ) 52 { 53 xx = x + sj[i][0] , yy = y + sj[i][1] , now = tote + sg[i] ; 54 if( xx < 1 || yy < 1 || xx > n || yy > m ) continue ; 55 if( jv[xx][yy] != 2 ) 56 { 57 add( tote , now , 1 ) ; 58 add( now , tote , 0 ) ; 59 } 60 } 61 } 62 63 64 void input( ) 65 { 66 n = read( ) , m = read( ) ; 67 tot = 0 ; cnt = -1 ; 68 s = 0 , t = n * m + 1 ; 69 sg[0] = 1 , sg[1] = -1 , sg[2] = m , sg[3] = 0 - m ; 70 memset( head , -1 , sizeof(head) ) ; 71 for( int x = 1 ; x <= n ; ++x ) 72 for( int y = 1 ; y <= m ; ++y ) 73 jv[x][y] = read( ) ; 74 for( int x = 1 ; x <= n ; ++x ) 75 for( int y = 1 ; y <= m ; y ++ ) 76 { 77 tot ++ ; 78 if( jv[x][y] != 1 ) link( x , y , tot ) ; 79 else 80 { 81 add( tot , t , inf ) ; 82 add( t , tot , 0 ) ; 83 } 84 } 85 } 86 87 88 bool bfs( ) 89 { 90 memset( dis , -1 , sizeof( dis ) ) ; 91 dis[0] = 0 ; Q.push( 0 ) ; 92 while( !Q.empty( ) ) 93 { 94 int u = Q.front( ) ; Q.pop( ) ; 95 for( int i = head[u] ; ~i ; i = edge[i].nxt ) 96 { 97 int v = edge[i].to ; 98 if( dis[v] < 0 && edge[i].val > 0 ) 99 { 100 dis[v] = dis[u] + 1 ; 101 Q.push( v ) ; 102 } 103 } 104 } 105 return dis[t] > 0 ; 106 } 107 108 109 int dfs( int u , int tmp ) 110 { 111 if( u == t ) return tmp ; 112 int an = 0 , cost = 0 ; 113 for( int i = cur[u] ; ~i ; i = edge[i].nxt ) 114 { 115 int v = edge[i].to ; 116 if( dis[v] != dis[u] + 1 ) continue ; 117 an = dfs( v , min( tmp -cost , edge[i].val ) ) ; 118 edge[i].val -= an ; edge[i^1].val += an ; cost += an; 119 if( edge[i].val ) cur[u] = i ; 120 if( tmp == cost ) return cost ; 121 } 122 if( !cost ) dis[u] = -1 ; 123 return cost ; 124 } 125 126 127 void sov( ) 128 { 129 while( bfs( ) ) 130 { 131 for( int i = 0 ; i <= t ; i++ ) cur[i] = head[i] ; 132 ans +=dfs( 0 , inf ) ; 133 } 134 printf( "%d " , ans ) ; 135 } 136 137 138 int main( ) 139 { 140 // Init( ) ; 141 input( ) ; 142 sov( ) ; 143 // fclose( stdin ) ; 144 // fclose( stdout ) ; 145 return 0 ; 146 }