1 条题解

  • 0
    @ 2025-11-3 9:33:12
    /*
    我们只需要寻找 n 个不同行列的黑格(可以反证自己想下)。
    因为我们没法确定在一行中选哪些格子,从而无法直接判断有无解。
    直接判断反例:
    1 1 0 0
    1 1 0 0
    1 1 0 0
    0 0 1 1
    (无解)
     
    这种有多个单位,多个可匹配点,甚至可能有多种匹配方式的问题,
    我们考虑使用最大二分图匹配来解决。
    将每一行连到每一行上所在的点,点再连到所在的列。 
    (代码中这里就直接有点就行连列) 
    如果每一对不同的行都有唯一匹配 (行,列) 的话,
    那么就有解。 
    这样使每个行节点都匹配到一个唯一的列节点,
    而且黑点正好处于(行,列)上,满足要求。 
    */
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 210;
    
    vector<int> G[N];
    int tsp, chw[N], match[N];
    // 时间戳,该列当前循环有没有被匹配过,列的匹配对象行 
    
    bool findmuniu(int x) {
    	for(int y : G[x]) if (chw[y] != tsp) {
    		chw[y] = tsp;
    		if (match[y] == 0 || (findmuniu(match[y]) == 1)) {
    			match[y] = x;
    			return 1;
    		}
    	}
    	return 0;
    }
    
    int main () {
    	ios::sync_with_stdio(false);;
    	cin.tie(0);
    	
    	int T;
    	cin >> T;
    	while (T --) {
    		int n;
    		cin >> n;
    		for (int i = 1; i <= n; i ++) {
    			G[i].clear();      // 多测不清空,亲人两行泪 
    			for (int j = 1; j <= n; j ++) {
    				int x;
    				cin >> x;
    				if (x == 1) {
    					G[i].push_back(j);
    				}
    			}
    		}
    		
    		bool flag = 1;
    		tsp = 0;
    		memset(chw, 0, sizeof(chw));
    		memset(match, 0, sizeof(match));
    		for (int i = 1; i <= n; i ++) {
    			tsp ++;
    			if (!findmuniu(i)) {
    				flag = 0;
    				break;
    			}
    		}
    		
    		if (flag == 1) {
    			cout << "Yes" << "\n";
    		}
    		else {
    			cout << "No" << "\n";
    		}
    	}
    	
    	return 0;
    } 
    
    
    • 1

    信息

    ID
    2712
    时间
    1000ms
    内存
    256MiB
    难度
    5
    标签
    递交数
    30
    已通过
    13
    上传者