BZOJ 2150: 部落战争 最大流

时间:2023-12-20 16:22:08

2150: 部落战争

Time Limit: 1 Sec

Memory Limit: 256 MB

题目连接

http://www.lydsy.com/JudgeOnline/problem.php?id=2150

Description

lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土。 A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住。lanzerb把自己的部落分成若干支军队,他们约定: 1. 每支军队可以从任意一个城镇出发,并只能从上往向下征战,不能回头。途中只能经过城镇,不能经过高山深涧。 2. 如果某个城镇被某支军队到过,则其他军队不能再去那个城镇了。 3. 每支军队都可以在任意一个城镇停止征战。 4. 所有军队都很奇怪,他们走的方法有点像国际象棋中的马。不过马每次只能走1*2的路线,而他们只能走R*C的路线。 lanzerb的野心使得他的目标是统一全国,但是兵力的限制使得他们在配备人手时力不从心。假设他们每支军队都能顺利占领这支军队经过的所有城镇,请你帮lanzerb算算至少要多少支军队才能完成统一全国的大业。

Input

第一行包含4个整数M、N、R、C,意义见问题描述。接下来M行每行一个长度为N的字符串。如果某个字符是'.',表示这个地方是城镇;如果这个字符时'x',表示这个地方是高山深涧。

Output

输出一个整数,表示最少的军队个数。

Sample Input

3 3 1 2
...
.x.
...

Sample Output

4

HINT

题意

题解:

最小路径覆盖问题

用总数减去最大流就好了

代码:

//qscqesze
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <bitset>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 200500
#define mod 1001
#define eps 1e-9
#define pi 3.1415926
int Num;
//const int inf=0x7fffffff;
const ll inf=;
inline ll read()
{
ll x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
//************************************************************************************* namespace NetFlow
{
const int MAXN=,MAXM=,inf=1e9;
struct Edge
{
int v,c,f,nx;
Edge() {}
Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
} E[MAXM];
int G[MAXN],cur[MAXN],pre[MAXN],dis[MAXN],gap[MAXN],N,sz;
void init(int _n)
{
N=_n,sz=; memset(G,-,sizeof(G[])*N);
}
void link(int u,int v,int c)
{
E[sz]=Edge(v,c,,G[u]); G[u]=sz++;
E[sz]=Edge(u,,,G[v]); G[v]=sz++;
}
int ISAP(int S,int T)
{//S -> T
int maxflow=,aug=inf,flag=false,u,v;
for (int i=;i<N;++i)cur[i]=G[i],gap[i]=dis[i]=;
for (gap[S]=N,u=pre[S]=S;dis[S]<N;flag=false)
{
for (int &it=cur[u];~it;it=E[it].nx)
{
if (E[it].c>E[it].f&&dis[u]==dis[v=E[it].v]+)
{
if (aug>E[it].c-E[it].f) aug=E[it].c-E[it].f;
pre[v]=u,u=v; flag=true;
if (u==T)
{
for (maxflow+=aug;u!=S;)
{
E[cur[u=pre[u]]].f+=aug;
E[cur[u]^].f-=aug;
}
aug=inf;
}
break;
}
}
if (flag) continue;
int mx=N;
for (int it=G[u];~it;it=E[it].nx)
{
if (E[it].c>E[it].f&&dis[E[it].v]<mx)
{
mx=dis[E[it].v]; cur[u]=it;
}
}
if ((--gap[dis[u]])==) break;
++gap[dis[u]=mx+]; u=pre[u];
}
return maxflow;
}
bool bfs(int S,int T)
{
static int Q[MAXN]; memset(dis,-,sizeof(dis[])*N);
dis[S]=; Q[]=S;
for (int h=,t=,u,v,it;h<t;++h)
{
for (u=Q[h],it=G[u];~it;it=E[it].nx)
{
if (dis[v=E[it].v]==-&&E[it].c>E[it].f)
{
dis[v]=dis[u]+; Q[t++]=v;
}
}
}
return dis[T]!=-;
}
int dfs(int u,int T,int low)
{
if (u==T) return low;
int ret=,tmp,v;
for (int &it=cur[u];~it&&ret<low;it=E[it].nx)
{
if (dis[v=E[it].v]==dis[u]+&&E[it].c>E[it].f)
{
if (tmp=dfs(v,T,min(low-ret,E[it].c-E[it].f)))
{
ret+=tmp; E[it].f+=tmp; E[it^].f-=tmp;
}
}
}
if (!ret) dis[u]=-; return ret;
}
int dinic(int S,int T)
{
int maxflow=,tmp;
while (bfs(S,T))
{
memcpy(cur,G,sizeof(G[])*N);
while (tmp=dfs(S,T,inf)) maxflow+=tmp;
}
return maxflow;
}
}
using namespace NetFlow; string s[];
int M[][][];
int tot=;
int get_id(int x,int y,int z)
{
if(M[x][y][z])return M[x][y][z];
else return M[x][y][z]=tot++;
}
int n,m,r,c;
int judge(int x,int y)
{
if(x>=n||x<)return ;
if(y>=m||y<)return ;
if(s[x][y]=='.')
return ;
return ;
}
int main()
{
init();
n=read(),m=read(),c=read(),r=read();
for(int i=;i<n;i++)
cin>>s[i];
int ans = ;
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
if(s[i][j]=='.')
{
ans++;
link(get_id(,,),get_id(i,j,),);
link(get_id(i,j,),get_id(,,),);
int x,y;
x=i+r;y=j+c;
if(judge(x,y))link(get_id(i,j,),get_id(x,y,),);
x=i+r;y=j-c;
if(judge(x,y))link(get_id(i,j,),get_id(x,y,),);
x=i+c;y=j+r;
if(judge(x,y))link(get_id(i,j,),get_id(x,y,),);
x=i+c;y=j-r;
if(judge(x,y))link(get_id(i,j,),get_id(x,y,),);
}
}
}
int K = dinic(get_id(,,),get_id(,,));
printf("%d\n",ans - K);
}