• 二分图总结


    大佬总结

    通俗有趣的讲解

    二分图判定(染色法)

    poj 2492

    #include<cstdio>
    #include<cstring>
    #define REP(i, a, b) for(register int i = (a); i < (b); i++)
    #define _for(i, a, b) for(register int i = (a); i <= (b); i++)
    using namespace std;
    
    const int MAXN = 2000 + 10;
    const int MAXM = 1e6 + 10;
    struct Edge { int to, next; };
    Edge edges[MAXM << 1];
    int head[MAXN], vis[MAXN];
    int color[MAXN],  n, m, num = 0;
    
    void addEdge(int from, int to)
    {
    	edges[num] = Edge{to, head[from]};
    	head[from] = num++;
    }
    
    bool dfs(int u)
    {
    	vis[u] = 1;
    	for(int i = head[u]; ~i; i = edges[i].next)
    	{
    		int v = edges[i].to;
    		if(vis[v])
    		{
    			if(color[u] == color[v]) return false;
    		}
    		else
    		{
    			color[v] = color[u] ^ 1;
    			if(!dfs(v)) return false;
    		}
    	}
    	return true;
    }
    
    bool judge()
    {
    	_for(i, 1, n)
    		if(!vis[i])
    		{
    			color[i] = 0;
    			if(!dfs(i)) return false;
    		}
    	return true;
    }
    
    int main()
    {
    	int T;
    	scanf("%d", &T);
    	
    	_for(kase, 1, T)
    	{
    		memset(head, -1, sizeof(head));
    		memset(vis, 0, sizeof(vis));
    		memset(color, 0, sizeof(color));
    		num = 0;
    		
    		scanf("%d%d", &n, &m);
    		while(m--)
    		{
    			int u, v;
    			scanf("%d%d", &u, &v);
    			addEdge(u, v); addEdge(v, u); 
    		}
    		
    		printf("Scenario #%d:
    ", kase);
    		if(!judge()) puts("Suspicious bugs found!
    ");
    		else puts("No suspicious bugs found!
    ");
    	}
    	
    	return 0;
    }

    二分图最大匹配 ——匈牙利算法

    最小覆盖点集 = 最大匹配

    poj 3041

    把矩阵上的点转化成边。点(x,y)即把x和y连一条边。

    最后答案即是最小覆盖点集,又知最小覆盖点集 = 最大匹配

    所以敲一遍模板就好了

    #include<cstdio>
    #include<cstring>
    #define REP(i, a, b) for(register int i = (a); i < (b); i++)
    #define _for(i, a, b) for(register int i = (a); i <= (b); i++)
    using namespace std;
    
    const int MAXN = 500 + 10;
    const int MAXM = 1e4 + 10;
    struct Edge
    {
    	int to, next;
    }e[MAXM];
    int vis[MAXN], head[MAXN];
    int link[MAXN], n, m, num, ans;
    
    void AddEdge(int from, int to)
    {
    	e[num] = Edge{to, head[from]}; 
    	head[from] = num++;
    }
    
    bool find(int u)
    {
    	for(int i = head[u]; ~i; i = e[i].next)
    	{
    		int v = e[i].to;
    		if(vis[v]) continue;
    		vis[v] = 1;
    		if(!link[v] || find(link[v]))
    		{
    			link[v] = u;
    			return true;
    		}
    	}
    	return false;
    }
    
    int main()
    {
    	memset(head, -1, sizeof(head)); num = 0;
    	memset(link, 0, sizeof(link));
    	scanf("%d%d", &n, &m);
    	
    	while(m--)
    	{
    		int u, v;
    		scanf("%d%d", &u, &v);
    		AddEdge(u, v);
    	}
    		
    	_for(i, 1, n)
    	{
    		memset(vis, 0, sizeof(vis));
    		if(find(i)) ans++;
    	}
    	printf("%d
    ", ans);
    	
    	return 0;
    }

    poj 1274

    裸题。二分图的题目要注意点和边数组开的大小。

    #include<cstdio>
    #include<cstring>
    #define REP(i, a, b) for(register int i = (a); i < (b); i++)
    #define _for(i, a, b) for(register int i = (a); i <= (b); i++)
    using namespace std;
    
    const int MAXN = 200 + 10;
    const int MAXM = 4e4 + 10;
    struct Edge{ int to, next; };
    Edge e[MAXM];
    int head[MAXN], vis[MAXN];
    int link[MAXN], n, m, num;
    
    void AddEdge(int from, int to)
    {
    	e[num] = Edge{to, head[from]};
    	head[from] = num++;
    }
    
    bool find(int u)
    {
    	for(int i = head[u]; ~i; i = e[i].next)
    	{
    		int v = e[i].to;
    		if(vis[v]) continue;
    		vis[v] = 1;
    		if(!link[v] || find(link[v]))
    		{
    			link[v] = u;
    			return true;
    		}
    	}
    	return false;
    }
    
    int main()
    {
    	while(~scanf("%d%d", &n, &m))
    	{
    		memset(head, -1, sizeof(head));
    		memset(link, 0, sizeof(link));
    		num = 0;
    		
    		_for(v, 1, n)
    		{
    			int t, u; scanf("%d", &t);
    			while(t--)
    			{
    				scanf("%d", &u);
    				AddEdge(u, v); 
    			}
    		}
    	
    		int ans = 0;
    		_for(i, 1, n)
    		{
    			memset(vis, 0, sizeof(vis));
    			if(find(i)) ans++;	
    		}
    		printf("%d
    ", ans);
    	}
    
    	return 0;
    }
  • 相关阅读:
    Oralce两种认证方式的总结
    MOSS2007启用发布Feature后,子站点标签无法高亮
    c#事务的使用、示例及注意事项 转
    软件标准项目文档(转)
    .net常用JS代码
    Epplus
    MOSS2007中自定义页面
    步步为营 SharePoint 开发学习笔记系列总结(转)
    SharePoint 2010 自定义Ribbon实现文档批量下载为Zip文件(转)
    显示详细的SharePoint错误
  • 原文地址:https://www.cnblogs.com/sugewud/p/9819313.html
Copyright © 2020-2023  润新知