大意:给你一些人,有些相互认识,有些不认识,问你是否能将不认识的分在一组,如果不能,输出No,如果可以,输出可以预定的双人间的最大值。
思路:
1、交叉染色法判断二分图。
2、二分图最大匹配。
我敲的时候出现了小错误,然后爆栈了。以为是DFS太多导致,于是我改用队列实现的交叉染色,过了。敲二分匹配时突然发现了一个小错误,明白了是这个导致了爆栈。然后回过头去改DFS实现的交叉染色,Hdu的数据实在是太水了,有些地方我一不小心改成错误的,还是过了,但这在UVA上是绝对过不了的,比如UVA 10004二分染色。
CODE:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
using namespace std;
const int MAXN = 210;
const int MAXM = 210*210;
struct Edge
{
int v, next;
}edge[MAXM];
int n, m;
int cnt;
int first[MAXN], link[MAXN];
bool vis1[MAXN], color[MAXN], vis2[MAXN];
void init()
{
cnt = 0;
memset(first, -1, sizeof(first));
memset(vis1, 0, sizeof(vis1));
memset(color, 0, sizeof(color));
memset(link, -1, sizeof(link));
}
void read_graph(int u, int v)
{
edge[cnt].v = v;
edge[cnt].next = first[u], first[u] = cnt++;
}
void read_graph2()
{
while(m--)
{
int u, v;
scanf("%d%d", &u, &v);
read_graph(u, v);
read_graph(v, u);
}
}
queue<int> q;
int Bicolor(int src)
{
while(!q.empty()) q.pop();
vis1[src] = 1;
q.push(src);
while(!q.empty())
{
int u = q.front(); q.pop();
for(int e = first[u]; e != -1; e = edge[e].next)
{
int v = edge[e].v;
if(!vis1[v])
{
vis1[v] = 1;
color[v] = !color[u]; //写错了,写成color[v] = !color[v]也过,Hdu数据太水了。
q.push(v);
}
else if(color[u] == color[v]) return false;
}
}
return true;
} //队列实现的交叉染色
/*int Bicolor(int u) //DFS实现的交叉染色
{
for(int e = first[u]; e != -1; e = edge[e].next)
{
int v = edge[e].v;
if(!vis1[v])
{
vis1[v] = 1;
color[v] = !color[u];
Bicolor(v);
}
else if(color[u] == color[v]) return false;
}
return true;
}*/
int ED(int u)
{
for(int e = first[u]; e != -1; e = edge[e].next)
{
int v = edge[e].v;
if(!vis2[v])
{
vis2[v] = 1; //写成vis2[1] = 1;爆栈了。。。
if(link[v] == -1 || ED(link[v]))
{
link[v] = u;
return true;
}
}
}
return false;
}
void solve(int src)
{
int ans = 0;
vis1[src] = 1; //很重要,不然会WA。
if(!Bicolor(src))
{
printf("No\n");
return ;
}
for(int i = 1; i <= n; i++)
{
memset(vis2, 0, sizeof(vis2));
if(ED(i)) ans++;
}
printf("%d\n", ans/2);
}
int main()
{
while(~scanf("%d%d", &n, &m))
{
init();
read_graph2();
solve(1);
}
return 0;
}
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
using namespace std;
const int MAXN = 210;
const int MAXM = 210*210;
struct Edge
{
int v, next;
}edge[MAXM];
int n, m;
int cnt;
int first[MAXN], link[MAXN];
bool vis1[MAXN], color[MAXN], vis2[MAXN];
void init()
{
cnt = 0;
memset(first, -1, sizeof(first));
memset(vis1, 0, sizeof(vis1));
memset(color, 0, sizeof(color));
memset(link, -1, sizeof(link));
}
void read_graph(int u, int v)
{
edge[cnt].v = v;
edge[cnt].next = first[u], first[u] = cnt++;
}
void read_graph2()
{
while(m--)
{
int u, v;
scanf("%d%d", &u, &v);
read_graph(u, v);
read_graph(v, u);
}
}
queue<int> q;
int Bicolor(int src)
{
while(!q.empty()) q.pop();
vis1[src] = 1;
q.push(src);
while(!q.empty())
{
int u = q.front(); q.pop();
for(int e = first[u]; e != -1; e = edge[e].next)
{
int v = edge[e].v;
if(!vis1[v])
{
vis1[v] = 1;
color[v] = !color[u]; //写错了,写成color[v] = !color[v]也过,Hdu数据太水了。
q.push(v);
}
else if(color[u] == color[v]) return false;
}
}
return true;
} //队列实现的交叉染色
/*int Bicolor(int u) //DFS实现的交叉染色
{
for(int e = first[u]; e != -1; e = edge[e].next)
{
int v = edge[e].v;
if(!vis1[v])
{
vis1[v] = 1;
color[v] = !color[u];
Bicolor(v);
}
else if(color[u] == color[v]) return false;
}
return true;
}*/
int ED(int u)
{
for(int e = first[u]; e != -1; e = edge[e].next)
{
int v = edge[e].v;
if(!vis2[v])
{
vis2[v] = 1; //写成vis2[1] = 1;爆栈了。。。
if(link[v] == -1 || ED(link[v]))
{
link[v] = u;
return true;
}
}
}
return false;
}
void solve(int src)
{
int ans = 0;
vis1[src] = 1; //很重要,不然会WA。
if(!Bicolor(src))
{
printf("No\n");
return ;
}
for(int i = 1; i <= n; i++)
{
memset(vis2, 0, sizeof(vis2));
if(ED(i)) ans++;
}
printf("%d\n", ans/2);
}
int main()
{
while(~scanf("%d%d", &n, &m))
{
init();
read_graph2();
solve(1);
}
return 0;
}