• BZOJ1059或洛谷1129 [ZJOI2007]矩阵游戏


    BZOJ原题链接

    洛谷原题链接

    通过手算几组例子后,很容易发现,同一列的(1)永远在这一列,且这些(1)有且仅有一个能产生贡献,行同理。
    所以我们可以只考虑交换列,使得每一行都能匹配一个(1),且每一行匹配的(1)没有重列的,最后交换行排序下即可达到目标。
    解决这个问题就不难了,对于一个格子((x,y)),若为(1),则从它所在的行(x)向列(y)连一条边,跑一边二分图最大匹配,判断是否是完全匹配即可。

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 1010;
    const int M = 1e5 + 10;
    int fi[N], ne[M], di[M], mtc[N], l;
    bool v[N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y)
    {
    	di[++l] = y;
    	ne[l] = fi[x];
    	fi[x] = l;
    }
    bool dfs(int x)
    {
    	int i, y;
    	for (i = fi[x]; i; i = ne[i])
    		if (!v[y = di[i]])
    		{
    			v[y] = 1;
    			if (!mtc[y] || dfs(mtc[y]))
    			{
    				mtc[y] = x;
    				return true;
    			}
    		}
    	return false;
    }
    int main()
    {
    	int i, j, n, s, x, t;
    	t = re();
    	while (t--)
    	{
    		n = re();
    		memset(mtc, 0, sizeof(mtc));
    		memset(fi, 0, sizeof(fi));
    		s = l = 0;
    		for (i = 1; i <= n; i++)
    			for (j = 1; j <= n; j++)
    			{
    				x = re();
    				if (x)
    					add(i, j + n);
    			}
    		for (i = 1; i <= n; i++)
    		{
    			memset(v, 0, sizeof(v));
    			if (dfs(i))
    				s++;
    		}
    		s ^ n ? printf("No
    ") : printf("Yes
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    Some interesting problems in Group theory
    Abstract Harmonic Analysis Lecture Notes
    郭懋正《实变函数与泛函分析》课后题答案
    江泽坚《泛函分析》第二版 参考答案
    国外著名数学杂志
    郑继明等《数值分析》习题解答
    《摩诃般若波罗蜜多心经》新译 何新 译
    炼静
    金刚经原文
    道德经全文
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9803641.html
Copyright © 2020-2023  润新知