BZOJ 2150: 部落战争 最大流

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);
}
时间: 2024-10-06 00:04:22

BZOJ 2150: 部落战争 最大流的相关文章

BZOJ 2150 部落战争(最小路径覆盖)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2150 题意:一个n*m的国家,有些是障碍.对于一支军队,每次只能走C*R的格式(比如马是走1*2的格式),而且只能从上往下走.每个格子只能被一个军队经过.问最少需要多少军队可以遍历完所有格子? 思路:上下能连边的连边.最后就是最小路径覆盖. int a[N][N],n,m; char s[55][55]; int ID(int i,int j) { return (i-1)*m+j;

[Bzoj ]2150 部落战争

2150: 部落战争(二分图匹配...) Description lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土. A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住.lanzerb把自己的部落分成若干支军队,他们约定: 1. 每支军队可以从任意一个城镇出发,并只能从上往向下征战,不能回头.途中只能经过城镇,不能经过高山深涧. 2. 如果某个城镇被某支军队到过,则其他军队不能再去那个城镇了. 3. 每支军队都可以在任意一个城

BZOJ 2150 部落战争 最小路径覆盖 二分图最大匹配

题目大意:给出一张地图,一个军队要征战整个土地.一块土地只能经过一次,有X的地方不能走,军队只会走R*C个格子,只会向下走,问最少需要多少军队能够征战所有的土地. 思路:这个是前几天考试的题,今天居然发现时BZ的原题,还好当时A掉了... 看到每个土地只能经过一次就想到了网络流什么的,再一想想好像是最小路径覆盖啊,然后拆点,建图,Hungary,二分图最小路径覆盖=点数-最大匹配,没了.. CODE: #include <cstdio> #include <cstring> #in

BZOJ2150: 部落战争

题解: 把每个点拆成入点和出点,因为必须经过一次且只能经过一次.所以在两个点之间连一条上界=下界=1的边. 然后再s到每个入点连边,每个出点向t连边,点与点之间... 求最小流就可以过了... (感觉最小流神一般的存在...) 代码: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #inclu

BZOJ-2150部落战争(最小路径覆盖)

2150: 部落战争 Time Limit: 10 Sec  Memory Limit: 259 MB Description lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土. A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住.lanzerb把自己的部落分成若干支军队,他们约定: 1. 每支军队可以从任意一个城镇出发,并只能从上往向下征战,不能回头.途中只能经过城镇,不能经过高山深涧. 2. 如果某个城镇被某支军队到过,则

(拆点+最小路径覆盖) bzoj 2150

2150: 部落战争 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 518  Solved: 298[Submit][Status][Discuss] Description lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土. A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住.lanzerb把自己的部落分成若干支军队,他们约定: 1. 每支军队可以从任意一个城镇出发,并只能从

bzoj2150: 部落战争(匈牙利)

2150: 部落战争 题目:传送门 题解: 辣鸡数据..毁我AC率 先说做法,很容易就可以看出是二分图匹配的最小路径覆盖(可能是之前不久刚做过类似的题) 一开始还傻逼逼的去直接连边然后准备跑floyd...肯定是做祭祀做傻了 二分图嘛,将每个点拆成两个集合再连啊... 然后最小路径覆盖=总点数-最大匹配数 强烈吐槽!个人习惯用数组存点编号...50*50的数据范围我开55*55...结果WA n次 然后...改成56*56...AC...ORZ 代码: 1 #include<cstdio> 2

BZOJ 2561 最小生成树(最大流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2561 题意:给定一个边带正权的连通无向图G= (V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在加入一条边权为L的边(u,v),那么需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树 上? 思路:考虑克鲁斯卡尔算法的过程.若加入的 边(u,v,L)能够出现在最小生成树中,那么权值小于L的边

BZOJ 2661 连连看(费用流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2661 题意:给出一个区间[a,b]中的全部整数,如果其中某两个数x,y(设x>y)的平方差x^2-y^2是一个完全平方数z^2,并且y与z互质,那么就可以将x和y一起消除,同时得到x+y点分数.要求就是,消除的数对尽可能多的前提下,得到的分数尽量多. 思路:首先暴力出所有合法的数对(x,y).然后将每个用到的数字拆成两个点,每个数对连一条边.最后的答案除以2即可. struct nod