您的位置:首页 > 其它

二分图的判断和二分图最大匹配模板

2015-05-11 13:22 393 查看
二分图的判定:是否能够将点集分成两个集合,使得对于每条边都有该边的一个点在一个集合,另一个在另一个集合。

hihocoder 1121  二分图判定

题目链接:hihocoder 1121

们的问题就转化为判定是否存在一个合理的染色方案,使得我们所建立的无向图满足每一条边两端的顶点颜色都不相同。

那么,我们不妨将所有的点初始为未染色的状态。随机选择一个点,将其染成白色。再以它为起点,将所有相邻的点染成黑色。再以这些黑色的点为起点,将所有与其相邻未染色的点染成白色。不断重复直到整个图都染色完成。(如下图)



在染色的过程中,我们应该怎样发现错误的记录呢?相信你一定发现了吧。对于一个已经染色的点,如果存在一个与它相邻的已染色点和它的颜色相同,那么就一定存在一条错误的记录。(如上图的4,5节点)

到此我们就得到了整个图的算法:

选取一个未染色的点u进行染色
遍历u的相邻节点v:若v未染色,则染色成与u不同的颜色,并对v重复第2步;若v已经染色,如果 u和v颜色相同,判定不可行退出遍历。
若所有节点均已染色,则判定可行。

分析:按照提示写出判断

#include<cstdio>
#include<vector>
#include<map>
#include<queue>
#include<string.h>
#include<iostream>
#include<cmath>
#include<algorithm>

using namespace std;

int vis[10005];
vector<int> vt[10005];
queue<int> qt;
int n,flag,t;

int main()
{
int cas,i,m,a,b;
scanf("%d",&cas);
while(cas--)
{
scanf("%d %d",&n,&m);

for(i=0;i<=n;i++)
vt[i].clear();
while(!qt.empty()) qt.pop();

for(i=0;i<m;i++)
{
scanf("%d %d",&a,&b);
vt[a].push_back(b);
}
if(n==1)
{
printf("Correct\n");
continue;
}
memset(vis,0,sizeof(vis));
vis[a]=1;
flag=0;
for(i=0;i<vt[a].size();i++)
{
vis[vt[a][i]]=2;
qt.push(vt[a][i]);
}
while(!qt.empty())
{
t=qt.front(); qt.pop();
for(i=0;i<vt[t].size();i++)
{
int tt=vt[t][i];
if( vis[tt]==0)
{
if(vis[t]==1) vis[tt]=2;
else vis[tt]=1;
qt.push(tt);
}
else if( vis[tt]==vis[t]) { flag=1; break; }
}
}
if(flag==1)
puts("Wrong");
else
puts("Correct");
}
}


二分图最大匹配的模板:
DFS实现:(邻接表 用vector数组实现)
const int maxn=512;
bool used[maxn];
vector<int>g[maxn];
int L,R;
int x[maxn],y[maxn];
bool SearchPath(int u)
{
int Size=g[u].size(),v;
for(int i=0;i<Size;i++)
{
v=g[u][i];
if(!used[v])
{
used[v] = true;
if(y[v] == -1 || SearchPath(y[v]))
{
y[v]=u;
x[u]=v;
return true;
}
}
}
return false;
}
int MaxMatch()
{
int ret=0;
memset(x,-1,sizeof(x));
memset(y,-1,sizeof(y));
for(int u=1;u<=L;u++)
{
if(x[u]==-1)
{
memset(used,false,sizeof(used));
if(SearchPath(u))
ret++;
}
}
return ret;
}

BFS实现:(邻接矩阵 用二维数组实现)
const int maxn=512;
int g[maxn][maxn];
int L,R;
int x[maxn],y[maxn];

int Q[maxn]; //模拟队列
int pre[maxn];
int MaxMatch()
{
int res=0,temp;
memset(x,-1,sizeof(x));
memset(y,-1,sizeof(y));
for(int i=1;i<=L;i++)
{
if(x[i]==-1)
{
int cur=0,tail=0;
for(int j=1;j<=R;j++)
{
if(g[i][j])
pre[j]=-1,Q[tail++]=j;
else
pre[j]=-2;
}

//BFS
while(cur<tail)
{
temp=Q[cur];
if(y[temp]==-1)
break;
cur++;
for(int j=1;j<=R;j++)
{
if(pre[j]==-2&&g[y[temp]][j])
{
pre[j]=temp;
Q[tail++]=j;
}
}
}
//end of BFS

if(cur==tail)  //没有找到交错轨
continue;
while(pre[temp]>-1)  //更改交错轨上匹配状态
{
x[ y[pre[temp]] ]=temp;
y[temp]=y[pre[temp]];
temp=pre[temp];
}
y[temp]=i;x[i]=temp;
res++;
}
}
return res;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二分图