BZOJ 2150: 部落戰爭 最大流

BZOJ 2150: 部落戰爭 最大流

轉自:https://www.cnblogs.com/qscqesze/p/4792682.html

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=999999999;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
//*************************************************************************************

namespace NetFlow
{
    const int MAXN=100000,MAXM=100000,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=0; memset(G,-1,sizeof(G[0])*N);
    }
    void link(int u,int v,int c)
    {
        E[sz]=Edge(v,c,0,G[u]); G[u]=sz++;
        E[sz]=Edge(u,0,0,G[v]); G[v]=sz++;
    }
    int ISAP(int S,int T)
    {//S -> T
        int maxflow=0,aug=inf,flag=false,u,v;
        for (int i=0;i<N;++i)cur[i]=G[i],gap[i]=dis[i]=0;
        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]+1)
                {
                    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]^1].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]])==0) break;
            ++gap[dis[u]=mx+1]; u=pre[u];
        }
        return maxflow;
    }
    bool bfs(int S,int T)
    {
        static int Q[MAXN]; memset(dis,-1,sizeof(dis[0])*N);
        dis[S]=0; Q[0]=S;
        for (int h=0,t=1,u,v,it;h<t;++h)
        {
            for (u=Q[h],it=G[u];~it;it=E[it].nx)
            {
                if (dis[v=E[it].v]==-1&&E[it].c>E[it].f)
                {
                    dis[v]=dis[u]+1; Q[t++]=v;
                }
            }
        }
        return dis[T]!=-1;
    }
    int dfs(int u,int T,int low)
    {
        if (u==T) return low;
        int ret=0,tmp,v;
        for (int &it=cur[u];~it&&ret<low;it=E[it].nx)
        {
            if (dis[v=E[it].v]==dis[u]+1&&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^1].f-=tmp;
                }
            }
        }
        if (!ret) dis[u]=-1; return ret;
    }
    int dinic(int S,int T)
    {
        int maxflow=0,tmp;
        while (bfs(S,T))
        {
            memcpy(cur,G,sizeof(G[0])*N);
            while (tmp=dfs(S,T,inf)) maxflow+=tmp;
        }
        return maxflow;
    }
}
using namespace NetFlow;

string s[100];
int M[52][52][3];
int tot=1;
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<0)return 0;
    if(y>=m||y<0)return 0;
    if(s[x][y]=='.')
        return 1;
    return 0;
}
int main()
{
    init(100000);
    n=read(),m=read(),c=read(),r=read();
    for(int i=0;i<n;i++)
        cin>>s[i];
    int ans = 0;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(s[i][j]=='.')
            {
                ans++;
                link(get_id(0,0,0),get_id(i,j,1),1);
                link(get_id(i,j,2),get_id(1,0,0),1);
                int x,y;
                x=i+r;y=j+c;
                if(judge(x,y))link(get_id(i,j,1),get_id(x,y,2),1);
                x=i+r;y=j-c;
                if(judge(x,y))link(get_id(i,j,1),get_id(x,y,2),1);
                x=i+c;y=j+r;
                if(judge(x,y))link(get_id(i,j,1),get_id(x,y,2),1);
                x=i+c;y=j-r;
                if(judge(x,y))link(get_id(i,j,1),get_id(x,y,2),1);
            }
        }
    }
    int K = dinic(get_id(0,0,0),get_id(1,0,0));
    printf("%d\n",ans - K);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章