zoukankan      html  css  js  c++  java
  • [HEOI2016/TJOI2016]游戏

    V.[HEOI2016/TJOI2016]游戏

    这题一开始想的是最小割,但是写着写着发现写不出来。看了标签,发现里面没有最小割,但是有连通块二分图。然后就想到了一种以前听说过的方法:连通块建图

    首先,对于任何一个关于\('x'\)\('*'\)连通的行连通块,这里面所有的\('*'\)中都只能选择一个填上炸弹;对于任何一个关于\('x'\)\('*'\)连通的列连通块,这里面所有的\('*'\)中也只能选择一个填上炸弹。

    而每个炸弹,一定且仅同时存在于一个行连通块与一个列连通块中。

    因此,我们可以将有交点,且交点是\('*'\)的行连通块和列连通块匹配;每有一对成功的匹配,就意味着可以多埋下一颗地雷。

    则最终答案即为匹配数。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,CB[110][110],RB[110][110],tot;
    char s[110][110];
    namespace MaxFlow{
    	const int N=10000,M=200000;
    	int head[N],cur[N],dep[N],cnt,S,T,res;
    	struct node{
    		int to,next,val;
    	}edge[M];
    	void ae(int u,int v,int w){
    		edge[cnt].next=head[u],edge[cnt].to=v,edge[cnt].val=w,head[u]=cnt++;
    		edge[cnt].next=head[v],edge[cnt].to=u,edge[cnt].val=0,head[v]=cnt++;
    	}
    	queue<int>q;
    	inline bool bfs(){
    		memset(dep,0,sizeof(dep)),q.push(S),dep[S]=1;
    		while(!q.empty()){
    			register int x=q.front();q.pop();
    			for(register int i=cur[x]=head[x];i!=-1;i=edge[i].next)if(edge[i].val&&!dep[edge[i].to])dep[edge[i].to]=dep[x]+1,q.push(edge[i].to);
    		}
    		return dep[T]>0;
    	}
    	bool reach;
    	inline int dfs(int x,int flow){
    		if(x==T){
    			res+=flow;
    			reach=true;
    			return flow;
    		}
    		int used=0;
    		for(register int &i=cur[x];i!=-1;i=edge[i].next){
    			if(!edge[i].val||dep[edge[i].to]!=dep[x]+1)continue;
    			register int ff=dfs(edge[i].to,min(edge[i].val,flow-used));
    			if(ff){
    				edge[i].val-=ff;
    				edge[i^1].val+=ff;
    				used+=ff;
    				if(used==flow)break;
    			}
    		}
    		return used;
    	}
    	inline void Dinic(){
    		while(bfs()){
    			reach=true;
    			while(reach)reach=false,dfs(S,0x3f3f3f3f);
    		}
    	}
    }
    using namespace MaxFlow;
    int main(){
    	scanf("%d%d",&n,&m),memset(head,-1,sizeof(head)),S=2*n*m,T=2*n*m+1;
    	for(int i=0;i<n;i++)scanf("%s",s[i]);
    	for(int i=0;i<n;i++)for(int j=0;j<m;j++){
    		if(!j||s[i][j-1]=='#')RB[i][j]=++tot,ae(S,tot,1);
    		else RB[i][j]=RB[i][j-1];
    	}
    	for(int j=0;j<m;j++)for(int i=0;i<n;i++){
    		if(!i||s[i-1][j]=='#')CB[i][j]=++tot,ae(tot,T,1);
    		else CB[i][j]=CB[i-1][j];
    	}
    	for(int i=0;i<n;i++)for(int j=0;j<m;j++)if(s[i][j]=='*')ae(RB[i][j],CB[i][j],1);
    	Dinic();
    	printf("%d\n",res);
    	return 0;
    }
    

  • 相关阅读:
    Java——HashMap
    Java——Collections
    Java——String,StringBuffer,StringBuilder
    OpenModelica读取文件
    Excel 常用设置
    Ubuntu16 源码方式安装postgresql数据库
    Utunbu常见问题
    PostgreSQL 扩展开发基础教程
    《数据挖掘导论》
    高性能MySQL --- 读书笔记(2)
  • 原文地址:https://www.cnblogs.com/Troverld/p/14610790.html
Copyright © 2011-2022 走看看