zoukankan      html  css  js  c++  java
  • P1129 [ZJOI2007]矩阵游戏 二分图最大匹配

    https://www.luogu.com.cn/problem/P1129
    n*n个格子的矩阵有黑白两色,问是否能经过有限次行交换和列交换使得主多角线上都是黑色(用1表示)。
    主对角线上全是黑色,我们可以反着推,对于一个单位矩阵,任意次行交换列交换之后矩阵总是满足一个一个性质,每一行只与唯一的列交点为1,就是不存在任意两个点1的行数相等,也不存在列数相等。行交换列交换都是可逆的,所以如果矩阵满足这样的性质就一定可以交换得到主对角线都是1,找这样的性质首先想到了八皇后,用dfs去遍历,可是n的范围是200啊一定会超时的。最后看了题解,只能拍手称妙啊,佩服的五体投地。不是每一行都要存在有一个唯一的列为1,那不就相当于可以想象在行和列之间建条边,行和列分别是二分图两部分中的点,如果存在最大匹配等n就是可以满足那个性质,或者说是每个行都可以找到一个列与他匹配。接下来就是套板子了

    #include<iostream>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int N=210;
    int n,m,a[N][N];
    bool st[N]; 
    int p[N],h[N],e[N*N],ne[N*N],idx;
    void add(int a,int b)
    {
    	e[idx]=b;
    	ne[idx]=h[a];
    	h[a]=idx++;
     } 
    bool find(int x)
    {
    	for(int i=h[x];i!=-1;i=ne[i])
    	{
    		int y=e[i];
    		if(!st[y])
    		{
    			st[y]=1;
    			if(!p[y]||find(p[y]))
    			{
    				p[y]=x;//保存每一列是否匹配过以及和谁匹配
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    int main()
    {
    	ios::sync_with_stdio(0);
    	cin.tie(0);
    	cout.tie(0);
    	int t;
    	cin>>t;
    	while(t--)
    	{
    		memset(h,-1,sizeof h);
    		cin>>n;
    		idx=0;
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    			{
    				cin>>a[i][j];
    				if(a[i][j])
    					add(i,j);//只需要一条i到j的边就可以了
    			}
    		bool flag=1;
    		memset(p,0,sizeof p);
    		for(int i=1;i<=n;i++)
    		{
    			memset(st,0,sizeof st);//清空标记,给i匹配过程中都找过那些点
    			if(!find(i)) 
    			{
    				flag=0;
    				break;
    			} 
    		}
    		if(flag) cout<<"Yes"<<endl;
    		else cout<<"No"<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    akka并发编程练习
    使用selenium和chromedriver组合爬虫时,如果爬取的页面数量巨多,会出现占用内存逐渐增大知道程序崩溃的情况
    网易2017秋招编程题集合_以下代码全部来自牛客网
    牛客网_运行问题
    json和xml之间转换的好文
    Eclipse 启动时闪退问题解决方案
    关于opencv的文件配置详细内容
    第一个opencv声称图片_以及遇到的问题集锦
    好文收藏_关于find_first_not_of函数
    好文收藏readtxt_cpp
  • 原文地址:https://www.cnblogs.com/neflibata/p/12871772.html
Copyright © 2011-2022 走看看