1 条题解

  • 1
    @ 2023-11-2 10:08:34

    具体思路

    我们先来找性质。

    显然对于下面这样的一个图,一定是无解的。

    0 1 0
    0 1 1
    1 0 0
    

    因为你 (2,2)(2,2) 这个点你交换行,有 (2,3)(2,3) 这个点永远跟你同一行,交换列,有 (1,2)(1,2) 这个点永远跟你同一列。

    也就是你永远无法把你想要改变的点放到你想要的位置上。

    那就是一个二分图最大匹配问题。

    如果一个位置上有黑点,那么就将横坐标向纵坐标连边。

    最后跑一遍二分图最大匹配,看最大匹配是不是 nn 即可。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N=4e4+5,M=210;
    struct edge{
    	int x,y,pre;
    }a[2*N];
    int last[N],alen;
    void ins(int x,int y){
    	a[++alen]=edge{x,y,last[x]};
    	last[x]=alen;
    }
    int mp[M][M];
    int match[N],chw[N],tsp;
    bool query(int x){
    	for(int k=last[x];k;k=a[k].pre){
    		int y=a[k].y;
    		if(chw[y]!=tsp){
    			chw[y]=tsp;
    			if(!match[y]||query(match[y])){
    				match[y]=x;
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    int main(){
    	int t;scanf("%d",&t);
    	while(t--){
    		int n;scanf("%d",&n);
    		alen=1;memset(last,0,sizeof(last));
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=n;j++){
    				scanf("%d",&mp[i][j]);
    				if(mp[i][j]){
    					ins(i,j+n);
    				}
    			}
    		}
    		tsp=0;
    		memset(chw,0,sizeof(chw));
    		memset(match,0,sizeof(match));
    		int ans=0;
    		for(int i=1;i<=n;i++){
    			tsp=i;
    			if(query(i)){
    				ans++;
    			}
    		}
    		if(ans!=n){
    			puts("No");
    		}
    		else puts("Yes");
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    1059
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    (无)
    递交数
    23
    已通过
    15
    上传者