• 洛谷 [P2774] 方格取数问题


    二分图最大点权独立集

    通过题目描述我们可以很明显的看出要通过二分图建模,二分图求最大独立点集很容易,就是建立二分图求n-最小割,然而这里加入了权值,而且权值是在点上的,那么我们对于每个点连一条到源点或汇点的容量等于权值的边,求最小割即可,见胡伯涛论文

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int MAXN=25000,MAXM=500005;
    int s,t,head[MAXN],cur[MAXN],n,m,maxflow,tot,nume,dep[MAXN],ma[105][105],dx[4]={-1,1,0,0},dy[4]={0,0,1,-1};
    queue<int >q;
    struct edge{
    	int to,nxt,flow,cap;
    }e[MAXM];
    void adde(int from,int to,int cap){
    	e[++nume].to=to;
    	e[nume].cap=cap;
    	e[nume].nxt=head[from];
    	head[from]=nume;
    }
    bool bfs(){
    	memset(dep,0,sizeof(dep));
    	q.push(s);dep[s]=1;
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		for(int i=head[u];i;i=e[i].nxt){
    			int v=e[i].to;
    			if(!dep[v]&&e[i].flow<e[i].cap){
    				dep[v]=dep[u]+1;
    				q.push(v);
    			}
    		}
    	}
    	return dep[t];
    }
    int dfs(int u,int flow){
    	if(u==t) return flow;
    	int tot=0;
    	for(int i=head[u];i&&tot<flow;i=e[i].nxt){
    		int v=e[i].to;
    		if(dep[v]==dep[u]+1&&e[i].flow<e[i].cap){
    			if(int t=dfs(v,min(flow-tot,e[i].cap-e[i].flow))){
    				e[i].flow+=t;
    				e[((i-1)^1)+1].flow-=t;
    				tot+=t;
    			}
    		}
    	}
    	return tot;
    }
    void dinic(){
    	while(bfs()){
    		for(int i=s;i<=t;i++) cur[i]=head[i];
    		maxflow+=dfs(s,0x3f3f3f3f);
    		//cout<<1<<endl;
    	}
    }
    int main(){
    	cin>>m>>n;
    	s=0;t=m*n+1;
    
    	for(int i=1;i<=m;i++){
    		for(int j=1;j<=n;j++){
    			scanf("%d",&ma[i][j]);
    		}
    	}
    	for(int i=1;i<=m;i++){
    		for(int j=1;j<=n;j++){
    			if((i+j)&1){
    				for(int k=0;k<4;k++){
    					int x=i+dx[k],y=j+dy[k];
    					if(ma[x][y]){
    					//	cout<<i*n+j-n<<' '<<x*n+y-n<<endl;
    						adde(i*n+j-n,x*n+y-n,0x3f3f3f3f);
    						adde(x*n+y-n,i*n+j-n,0);
    					}
    				}
    				adde(s,i*n+j-n,ma[i][j]);adde(i*n+j-n,s,0);
    			}else adde(i*n+j-n,t,ma[i][j]),adde(t,i*n+j-n,0);
    			tot+=ma[i][j];
    		}
    	}
    	//for(int i=head[1];i;i=e[i].nxt) cout<<e[i].to<<endl;
    	dinic();
    	
    	cout<<tot-maxflow<<endl;
    	return 0;
    }
    
  • 相关阅读:
    JFinal框架
    shiro认证登录实现
    linux常用的命令
    zookeeper部署到linux操作步骤
    java的冒泡排序
    软件设计的七大原则
    vue知识点整理
    JVM垃圾回收算法
    Sql Server删库了怎么办?跑路是不可能跑路的
    Linux--find用法
  • 原文地址:https://www.cnblogs.com/Mr-WolframsMgcBox/p/8351536.html
Copyright © 2020-2023  润新知