• poj 2226 二分图 最小点覆盖 , 最大流



    题目就是问怎样用最小的板覆盖全部的草地。能够横着放。也能够竖着放,同意一个草地放多个点。

    建图方法就是 每一个横向的草地作为X,纵向连续的草地作为Y.     X连接Y的边表示,  这里有他们的公共点。。


    非常显然,覆盖全部草地,就是覆盖全部的边 ,二分图中。最小点覆盖 = 最大匹配

    = =事实上假设存在一条边未被选中的节点覆盖,则必定存在一条相应的增广路径

    //tpl
    //ipqhjjybj_tpl.h
    //header.h
    #include <cstdio>
    #include <cstdlib>
    #include <map>
    #include <set>
    #include <algorithm>
    #include <cstring>
    #include <iostream>
    #include <vector>
    #include <string>
    
    #define mp(x,y) make_pair(x,y)
    #define pii pair<int,int>
    #define pLL pair<long long ,long long>
    #define rep(i,j,k) for(int i = j; i < k;i++)
    
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    
    const int N = 500;
    int g[N][N];
    int cx[N],cy[N];
    int mark[N];
    int nx,ny;
    
    int dfs(int u)  
    {  
        rep(v,0,ny) 
        {  
            if(g[u][v]&&!mark[v])//u和v不要搞反了  
            {  
                mark[v]=1;  
                if(cy[v]==-1||dfs(cy[v]))  
                {  
                    cx[u]=v;  
                    cy[v]=u;  
                    return 1;  
                }  
            }  
        }  
        return 0;  
    }  
    int maxmatch()  
    {  
        int res=0;  
        memset(cx,-1,sizeof(cx));  
        memset(cy,-1,sizeof(cy));  
        rep(i,0,nx)
        {  
            if(cx[i]==-1)  
            {  
                memset(mark,0,sizeof(mark));  
                res+=dfs(i);  
            }  
        }  
    	// rep(i,0,nx){
    			// printf("cx[%d] = %d
    ",i,cx[i]);
    			// printf("cy[%d] = %d
    ",i,cy[i]);
    		// }
        return res;  
    }  
    
    int a[N][N],b[N][N];
    char s[N][N];
    int main(){
    	int n,m;
    	while(scanf("%d %d",&n,&m)!=EOF){
    		memset(g,0,sizeof(g));
    		rep(i,0,n) scanf("%s",s[i]);
    		int cnt = 0;
    		rep(i,0,n)
    			rep(j,0,m){
    				if(s[i][j]=='*'){
    					if(i==0 || s[i-1][j]=='.')
    						a[i][j] = cnt++;
    					else a[i][j] = a[i-1][j];
    				}
    			}
    		nx = cnt;
    		cnt = 0;
    		rep(i,0,n)
    			rep(j,0,m){
    				if(s[i][j] == '*'){
    					if(j==0 || s[i][j-1]=='.')
    						b[i][j] = cnt++;
    					else b[i][j] = b[i][j-1];
    					 g[a[i][j]][b[i][j]] = 1;
    				}				
    			}
    		ny = cnt;
    		// rep(i,0,nx){
    			// rep(j,0,ny)
    				// printf("g[%d][%d]=%d ",i,j,g[i][j]);
    			// printf("
    ");
    		// }
    		
    		printf("%d
    ",maxmatch());
    	}
    	return 0;
    }

    附上我的 最大流写法。

    //tpl
    //ipqhjjybj_tpl.h
    //header.h
    #include <cstdio>
    #include <cstdlib>
    #include <map>
    #include <set>
    #include <algorithm>
    #include <cstring>
    #include <iostream>
    #include <vector>
    #include <string>
    
    #define mp(x,y) make_pair(x,y)
    #define pii pair<int,int>
    #define pLL pair<long long ,long long>
    #define rep(i,j,k) for(int i = j; i < k;i++)
    
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    
    
    const int N = 1111;
    int tot;
    int s,t;
    int sum;
    struct node{
    	int u,v,w,next;
    	node(){}
    	node(int _u,int _v,int _w,int _next){
    		u=_u,v=_v,w=_w,next=_next;
    	}
    }edge[N*N];
    int head[N],cur[N],dis[N];
    int pre[N],gap[N],aug[N];
    const int oo=0x3f3f3f;
    void addEdge(int u,int v,int w){
    	edge[tot]=node(u,v,w,head[u]);
    	head[u]=tot++;
    	edge[tot]=node(v,u,0,head[v]);
    	head[v]=tot++;
    }
    
    int SAP(int s,int e,int n){
    	int max_flow=0,v,u=s;
    	int id,mindis;
    	aug[s]=oo;
    	pre[s]=-1;
    	memset(dis,0,sizeof(dis));
    	memset(gap,0,sizeof(gap));
    	gap[0]=n;
    
    	for(int i=0;i <= n;i++)
    		cur[i]=head[i];
    
    	while(dis[s]<n){
    		if(u==e){
    			max_flow += aug[e];
    			for(v=pre[e]; v!=-1; v=pre[v]){
    				int ed=cur[v];
    				edge[ed].w -= aug[e];
    				edge[ed^1].w += aug[e];
    				aug[v]-=aug[e];
    				if(edge[ed].w==0) u=v;
    			}
    		}
    		bool flag=false;
    		for(id=cur[u]; id!=-1;id=edge[id].next){
    			v=edge[id].v;
    			if(edge[id].w > 0 && dis[u]==dis[v]+1){
    				flag=true;
    				pre[v]=u;
    				cur[u]=id;
    				aug[v]=min(aug[u],edge[id].w);
    				u=v;
    				break;
    			}
    		}
    		if(flag==false){
    			if(--gap[dis[u]] == 0) break; 
    			int mindis=n;
    			for(id=head[u]; id!=-1; id=edge[id].next){
    				v=edge[id].v;
    				if(edge[id].w>0 && dis[v] < mindis){
    					mindis = dis[v];
    					cur[u]=id;
    				}
    			}
    			dis[u] = mindis + 1;
    			gap[dis[u]]++;
    			if(u!=s)u=pre[u];
    		}
    	}
    	return max_flow;
    }
    
    int a[N][N],b[N][N];
    char ss[N][N];
    int main(){
    	int n,m;
    	while(scanf("%d %d",&n,&m)!=EOF){
    		tot=sum=s=0;
    		int tc=0;
    		memset(head,-1,sizeof(head));
    
    		rep(i,0,n) scanf("%s",ss[i]);
    		int cnt = 0;
    		t = ++cnt;
    		rep(i,0,n)
    			rep(j,0,m){
    				if(ss[i][j]=='*'){
    					if(i==0 || ss[i-1][j]=='.')
    						a[i][j] = ++cnt , addEdge(s,a[i][j],1);
    					else a[i][j] = a[i-1][j];
    				}
    			}
    	
    		rep(i,0,n)
    			rep(j,0,m){
    				if(ss[i][j] == '*'){
    					
    					if(j==0 || ss[i][j-1]=='.')
    						b[i][j] = ++cnt ,addEdge(b[i][j],t,1);
    					else b[i][j] = b[i][j-1];
    					//g[a[i][j]][b[i][j]] = 1;
    					addEdge(a[i][j],b[i][j],1);
    					
    				}				
    			}
    		
    		printf("%d
    ",SAP(s,t,cnt+1));
    	}
    	return 0;
    }


  • 相关阅读:
    python3中的线程简记
    python3中的SMTP简记
    sql依赖注入简记
    python Internet模块
    python-socket编程简例
    1.docker简介及安装
    kvm迁移
    kvm网络管理
    kvm存储池和存储卷
    2.标准数据类型--字符串
  • 原文地址:https://www.cnblogs.com/mthoutai/p/6749302.html
Copyright © 2020-2023  润新知