• 洛谷P2055 [ZJOI2009]假期的宿舍(二分图最大匹配)


    二分图最大匹配问题。把需要找床(非本校学生以及本校不回家学生)作为左部点,本校学生的床(以序号i + n存储为点)作为右部点,遍历关系矩阵,对于本校不回家学生和他的床连双向边,需要床的学生(本校不回家学生以及外校学生)和认识他的本校学生(无论回不回家)的床连边,跑匈牙利 or 网络流 求出来二分图最大匹配,看值是否等于需要床的学生数。

    注意及时memset和清除tot变量,以及临接表数组要开二倍和四倍的大小(存储双向边,以及点的个数是2 * n个)。

    #include <iostream>
    #include <cstring>
    using namespace std;
    int n, need, match[110];
    bool school[110], home[110], rela[110][110], vis[110];
    int head[110], ver[220], Next[220], tot = 0;
    void add(int x, int y)
    {
    	ver[++tot] = y, Next[tot] = head[x], head[x] = tot;
    }
    bool dfs(int x)
    {
    	for(int i = head[x], y; i; i = Next[i])
    	{
    		if(!vis[y = ver[i]])
    		{
    			vis[y] = 1;
    			if(!match[y] || dfs(match[y])){
    				match[y] = x;
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    int main()
    {
    	freopen("data.txt", "r", stdin);
    	ios::sync_with_stdio(false); 
    	int t;
    	cin >> t;
    	while(t--)
    	{
    		tot = 0;
    		memset(head, 0, sizeof(head));
    		cin >> n;
    		need = 0;
    		memset(match, 0, sizeof(match));
    		for(int i = 1; i <= n; i++)
    		{
    			cin >> school[i];
    		}
    		for(int i = 1; i <= n; i++)
    		{
    			cin >> home[i];
    			if(!school[i] || school[i] && (!home[i])) need++;
    		}
    		for(int i = 1; i <= n; i++)
    		{
    			for(int j = 1; j <= n; j++)
    			{
    				cin >> rela[i][j];
    				if(i == j && school[i] && (!home[i]))
    				{
    					add(i, i + n);
    					add(i + n, i);
    					continue;
    				}
    				if(rela[i][j])
    				{
    					if((school[i] && (!home[i]) || !school[i] ) && school[j])
    					{
    						add(i, j + n);
    						add(j + n, i);
    					}
    				}
    			}
    		}
    		for(int i = 1; i <= n; i++)
    		{
    			memset(vis, 0, sizeof(vis));
    			if(!school[i] || school[i] && (!home[i])) 
    			{
    				if(dfs(i)) need--;
    			}
    		}
    		if(!need)
    		{
    			cout << "^_^" << endl;
    		}
    		else cout << "T_T" << endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    常见的单链表题目
    一个string类的几个函数
    strcpy和memcpy的区别
    字符串及 strcpy几种写法
    什么函数不能声明为虚函数
    STL中Vector和List的底层数据结构
    C/C++堆、栈及静态数据区详解
    tcp四次握手
    几个知识点
    内存对齐的规则与作用
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/14411391.html
Copyright © 2020-2023  润新知