题目描述
lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土。
A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住。lanzerb把自己的部落分成若干支军队,他们约定:
-
每支军队可以从任意一个城镇出发,并只能从上往向下征战,不能回头。途中只能经过城镇,不能经过高山深涧。
-
如果某个城镇被某支军队到过,则其他军队不能再去那个城镇了。
-
每支军队都可以在任意一个城镇停止征战。
-
所有军队都很奇怪,他们走的方法有点像国际象棋中的马。不过马每次只能走1*2的路线,而他们只能走R*C的路线。
lanzerb的野心使得他的目标是统一全国,但是兵力的限制使得他们在配备人手时力不从心。假设他们每支军队都能顺利占领这支军队经过的所有城镇,请你帮lanzerb算算至少要多少支军队才能完成统一全国的大业。
输入输出格式
输入格式:
第一行包含4个整数M、N、R、C,意义见问题描述。接下来M行每行一个长度为N的字符串。如果某个字符是'.',表示这个地方是城镇;如果这个字符时'x',表示这个地方是高山深涧。
输出格式:
输出一个整数,表示最少的军队个数。
输入输出样例
输入样例#2: 复制
5 4 1 1 .... ..x. ...x .... x...
输出样例#2: 复制
View Code
5
- 很明显是二分图的最大路径覆盖问题 所以答案为点数-匹配数
- 所以s连每个空地入度 容量1 出度连t 容量1 能到的话 入度连出度 为1 答案为空地数-dinic
- 其实就是用网络流来做二分图匹配算法而已
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define inf 0x3f3f3f3f const int N=1e6; const int M=4e6+54; struct edge { int to, next, w; } e[M << 1]; int head[N], cnt = 1; void add(int x, int y, int z) { e[++cnt] = (edge){y, head[x], z}; head[x] = cnt; e[++cnt] = (edge){x, head[y], 0}; head[y] = cnt; } int level[N]; bool bfs(int s, int t) { memset(level, 0, sizeof level); queue<int> q; level[s] = 1; q.push(s); while (!q.empty()) { int pos = q.front(); q.pop(); for (int i = head[pos]; i; i = e[i].next) { int nx = e[i].to; if (!e[i].w || level[nx]) continue; level[nx] = level[pos] + 1; q.push(nx); } } return level[t]; } int dfs(int s, int t, int flow) { if (s == t) return flow; int ret = 0; for (int i = head[s]; flow && i; i = e[i].next) { int nx = e[i].to; if (level[nx] == level[s] + 1 && e[i].w) { int tmp = dfs(nx, t, min(flow, e[i].w)); e[i].w -= tmp; e[i ^ 1].w += tmp; flow -= tmp; ret += tmp; } } if (!ret) level[s] = 0; return ret; } int dinic(int s, int t) { int ret = 0; while (bfs(s, t)) ret += dfs(s, t, inf); return ret; } int n,m,s,t,a,b,c,r ; int dx[4],dy[4]; char mp[300][300]; int id(int x,int y) { return x*m+y; } int main() { cin>>n>>m>>r>>c; dy[0]=-r;dx[0]=c; dy[1]= r;dx[1]=c; dy[2]= c;dx[2]=r; dy[3]=-c;dx[3]=r; rep(i,1,n)RS(mp[i]+1); int sum=0; s=n*m*10+1,t=s+1; int T=n*m+m+n; rep(i,1,n) rep(j,1,m) { if(mp[i][j]=='.') { add(s,id(i,j),1); add(id(i,j)+T,t,1);sum++; rep(k,0,3) { int x=i+dx[k],y=j+dy[k]; if( x>n||x<1||y<1||y>m)continue; if(mp[x][y]!='.')continue; add(id(i,j),id(x,y)+T,1); } } } // printf("okok"); cout<<sum-dinic(s,t); return 0; }