zoukankan      html  css  js  c++  java
  • BZOJ 1059 [ZJOI2007]矩阵游戏

    题解:二分图匹配

    行列建点

    每一条边i->j表示第i行移动到第j行符合题意,即a[i][j]=1

    可证明不需考虑列的交换

    求最大匹配即可

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    const int maxn=300;
    const int oo=1000000000;
    
    int T;
    int n;
    
    struct Edge{
    	int from,to,cap,flow;
    };
    vector<int>G[maxn*maxn];
    vector<Edge>edges;
    void Addedge(int x,int y,int z){
    	Edge e;
    	e.from=x;e.to=y;e.cap=z;e.flow=0;
    	edges.push_back(e);
    	e.from=y;e.to=x;e.cap=0;e.flow=0;
    	edges.push_back(e);
    	int c=edges.size();
    	G[x].push_back(c-2);
    	G[y].push_back(c-1);
    }
    
    int s,t;
    int vis[maxn*maxn];
    int d[maxn*maxn];
    queue<int>q;
    int Bfs(){
    	memset(vis,0,sizeof(vis));
    	vis[s]=1;d[s]=0;q.push(s);
    	while(!q.empty()){
    		int x=q.front();q.pop();
    		for(int i=0;i<G[x].size();++i){
    			Edge e=edges[G[x][i]];
    			if((e.cap>e.flow)&&(!vis[e.to])){
    				vis[e.to]=1;
    				d[e.to]=d[x]+1;
    				q.push(e.to);
    			}
    		}
    	}
    	return vis[t];
    }
    
    int Dfs(int x,int a){
    	if((x==t)||(a==0))return a;
    	
    	int nowflow=0,f;
    	for(int i=0;i<G[x].size();++i){
    		Edge e=edges[G[x][i]];
    		if((d[x]+1==d[e.to])&&((f=Dfs(e.to,min(a,e.cap-e.flow)))>0)){
    			nowflow+=f;
    			a-=f;
    			edges[G[x][i]].flow+=f;
    			edges[G[x][i]^1].flow-=f;
    			if(a==0)break;
    		}
    	}
    	return nowflow;
    }
    
    int Maxflow(){
    	int flow=0;
    	while(Bfs())flow+=Dfs(s,oo);
    	return flow;
    }
    
    void Dinicinit(){
    	for(int i=0;i<=n+n+2;++i)G[i].clear();
    	edges.clear();
    	while(!q.empty())q.pop();
    }
    
    int main(){
    	scanf("%d",&T);
    	while(T--){
    		Dinicinit();
    		scanf("%d",&n);
    		s=n+n+1;t=s+1;
    		for(int i=1;i<=n;++i){
    			Addedge(s,i,1);
    			Addedge(i+n,t,1);
    		}
    		for(int i=1;i<=n;++i){
    			for(int j=1;j<=n;++j){
    				int x;
    				scanf("%d",&x);
    				if(x==1)Addedge(i,j+n,1);
    			}
    		}
    		if(Maxflow()==n)printf("Yes
    ");
    		else printf("No
    ");
    	}
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    android的一些类库的优缺点
    中文后乱码问题的解决方法(可能解决)
    android data recovery and nc
    最短路径——Floyd,Dijkstra(王道)
    还是畅通工程——最小生成树(王道)
    More is better——并查集求最大集合(王道)
    畅通工程——并查集(王道)
    IDEA默认VIM模式
    命令行杀死进程
    进制转换——高精度整数(王道)
  • 原文地址:https://www.cnblogs.com/zzyer/p/8475935.html
Copyright © 2011-2022 走看看