• 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;
    }
    
  • 相关阅读:
    Java下载execl表格
    ajax请求下载Execl表
    Spring Boot2.4双数据源的配置
    使用nginx对spring boot项目进行代理
    spring mvc中几种获取request对象的方式
    做开发十年,我总结一些开发经验
    linux基础指令以及权限管理
    ArrayList调用remove(int index)抛出UnsupportedOperationException问题分析以及解决记录
    ubuntu16.06+vsftpd+nginx搭建图片服务器
    RPC框架基础概念理解以及使用初体验
  • 原文地址:https://www.cnblogs.com/neflibata/p/12871772.html
Copyright © 2020-2023  润新知