zoukankan      html  css  js  c++  java
  • [HEOI2016/TJOI2016][bzoj4554] 游戏 [建图+最大流]

    题面

    传送门

    思路

    看到棋盘摆放和棋子冲突,再加上这么小的数据范围,你能想到什么?

    网络流棋盘模型啊!

    就是 把源点连到每一行,每一列连到汇点,再在中间......

    等等,这道题每行不一定全部冲突???

    这倒是个问题,但是依旧难不倒网络流大法

    我们考虑每一行中的一段“冲突区间”,就是两块硬石头中间的一段软石头和空地

    例如一行[##**x**#xx*x##*]就包含三个冲突区间[**x**][xx*x][*]

    那么显然每个冲突区间中只能摆放一个石子

    同理,我们对于每一列也划分这样的区间

    对于一个空地(i,j),我们将它所处的行区间和所处的列区间连起来,我们就得到了一个二分图

    那么此题的答案就是这个二分图的最大匹配

    我们再把源点连到所有行区间、汇点连到所有列区间,

    我们就得到了一个网络流模型,跑S-T最大流就是答案了

    Code:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    #define inf 1e9
    using namespace std;
    inline int read(){
        int re=0,flag=1;char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-') flag=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
        return re*flag;
    }
    int n,m,cnt=-1,ans=0,first[10010],dep[10010],cur[10010],x[101][101]={0},bx[101][101],by[101][101]; 
    struct edge{
        int to,next,w;
    }a[500010];
    inline void add(int u,int v,int w){
        a[++cnt]=(edge){v,first[u],w};first[u]=cnt;
        a[++cnt]=(edge){u,first[v],0};first[v]=cnt;
    }
    int q[10010];
    bool bfs(int s,int t){
        int head=0,tail=1,i,u,v;
        for(i=s;i<=t;i++) dep[i]=-1,cur[i]=first[i];
        q[0]=s;dep[s]=0;
        while(head<tail){
            u=q[head++];
            for(i=first[u];~i;i=a[i].next){
                v=a[i].to;
                if(~dep[v]||!a[i].w) continue;
                dep[v]=dep[u]+1;q[tail++]=v;
            }
        }
        return ~dep[t];
    }
    int dfs(int u,int t,int limit){
        if(u==t||!limit) return limit;
        int i,v,f,flow=0;
        for(i=cur[u];~i;i=a[i].next){
            v=a[i].to;cur[u]=i;
            if(dep[v]==dep[u]+1&&(f=dfs(v,t,min(limit,a[i].w)))){
                a[i].w-=f;a[i^1].w+=f;
                limit-=f;flow+=f;
                if(!limit) return flow;
            }
        }
        return flow;
    }
    void dinic(int s,int t){
        while(bfs(s,t)) ans+=dfs(s,t,inf);
    }
    int main(){	
        std::ios::sync_with_stdio(false);
        memset(first,-1,sizeof(first));
        cin>>n>>m;int i,j;char s[100];
        for(i=1;i<=n;i++){
            cin>>s;
            for(j=1;j<=m;j++){
                if(s[j-1]=='x') x[i][j]=2;
                if(s[j-1]=='*') x[i][j]=1;
                if(s[j-1]=='#') x[i][j]=0;
            }
        }
        int tmp=0,tt;
        for(i=1;i<=n;i++){
            for(j=1;j<=m;j++){
                if(!x[i][j]) continue;
                if((j==1)||(!x[i][j-1])) add(0,++tmp,1);
                bx[i][j]=tmp;
            }
        }
        for(j=1;j<=m;j++){
            for(i=1;i<=n;i++){
                if(!x[i][j]) continue;
                if((i==1)||(!x[i-1][j])) add(++tmp,n*m-1,1);
                by[i][j]=tmp;
            }
        }
        for(i=1;i<=n;i++){
            for(j=1;j<=m;j++){
                if(x[i][j]==1) add(bx[i][j],by[i][j],1);
            }
        }
        dinic(0,n*m-1);
        cout<<ans<<endl;
    }
    
  • 相关阅读:
    对Spring 框架 AOP(面向切面)的理解
    页面自动刷新
    页面通过ajax传值到后台,后台返回值展示在页面输入框
    java中怎么跳出两层for循环
    人的三种思维角度
    我理解的战争(程序员是需要有立场的)
    我所理解的JavaScript中的prototype与__proto__、constructor
    一个"失速"项目的总结
    TDD学习笔记
    Java SQL动态生成库
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/8759898.html
Copyright © 2011-2022 走看看