zoukankan      html  css  js  c++  java
  • P2172 [国家集训队]部落战争 最大流

      

    题目描述

    lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土。

    A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住。lanzerb把自己的部落分成若干支军队,他们约定:

    1. 每支军队可以从任意一个城镇出发,并只能从上往向下征战,不能回头。途中只能经过城镇,不能经过高山深涧。

    2. 如果某个城镇被某支军队到过,则其他军队不能再去那个城镇了。

    3. 每支军队都可以在任意一个城镇停止征战。

    4. 所有军队都很奇怪,他们走的方法有点像国际象棋中的马。不过马每次只能走1*2的路线,而他们只能走R*C的路线。

    lanzerb的野心使得他的目标是统一全国,但是兵力的限制使得他们在配备人手时力不从心。假设他们每支军队都能顺利占领这支军队经过的所有城镇,请你帮lanzerb算算至少要多少支军队才能完成统一全国的大业。

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    3 3 1 2
    ...
    .x.
    ...
    输出样例#1: 复制
    4
    输入样例#2: 复制
    5 4 1 1
    ....
    ..x.
    ...x
    ....
    x...
    输出样例#2: 复制
    5


    • 很明显是二分图的最大路径覆盖问题   所以答案为点数-匹配数
    • 所以s连每个空地入度 容量1    出度连t 容量1 能到的话 入度连出度 为1  答案为空地数-dinic   
    • 其实就是用网络流来做二分图匹配算法而已
    #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;
    }
    View Code


  • 相关阅读:
    屏蔽鼠标右键/F1帮助
    vs2010如何连接到mysql数据库
    经典的数据库设计贴吧
    js子窗口刷新父窗口
    数据库三大范式
    写给毕业生
    SQL Server权限数据库设计
    .NET
    ASP.NET MVC框架(第一部分) 【转】
    什么是SQL注入法攻击 .
  • 原文地址:https://www.cnblogs.com/bxd123/p/11233870.html
Copyright © 2011-2022 走看看