您的位置:首页 > 其它

HDU 2444 The Accomodation of Students (偶图判定,匈牙利算法)

2015-07-01 17:02 357 查看
题意:

  有一堆的学生关系,要将他们先分成两个组,同组的人都不互不认识,如果不能分2组,输出No。若能,则继续。在两组中挑两个认识的人(每组各1人)到一个双人房。输出需要多少个双人房?

思路:

  先判定是否为二分图,可以用黑白着色法(DFS或BFS都行)。若是二分图,再进行匹配,用匈牙利算法,注:给的是整个图,没有区分男女,用邻接表比较好。

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N=205;
vector< vector<int> > vect;
int col
;
int girl
;
int vis
;
int n, m;

bool color(const int x)   //x可达的点着色
{
for(int i=0; i<vect[x].size(); i++)
{
int t=vect[x][i];
if(col[x]==col[t])    return false;    //出错了,同色
if(!col[t])
{
col[t]=3-col[x];//性别标为1和2
if(color(t)==false)    return false;    //只有刚着色的才需要深搜
}
}
return true;   //只有单个点才会到这
}

bool is2()//二分图判断,注意其可能并不是个连通图
{
memset(col,0,sizeof(col));
for(int i=1; i<=n; i++) //黑白着色
{
if(!col[i]) //可能有多个连通分量
{
col[i]=1;
if(!color(i))
{
//cout<<i<<endl;
return false;
}
}
}
return true;
}

int find(int x)
{
for(int i=0; i<vect[x].size(); i++)
{
int t=vect[x][i];
if(!vis[t])
{
vis[t]=1;
if(!girl[t] || find(girl[t]))   //未匹配,或能为其对象另匹配
{
girl[t]=x;
return true;
}
}
}
return false;
}

int hungary()
{
int cnt=0;
memset(girl,0,sizeof(girl));
for(int i=1; i<=n; i++)
{
memset(vis,0,sizeof(vis));
if(find(i))    cnt++;
}
return cnt;
}

int main()
{
//freopen("input.txt", "r", stdin);
int a, b, c;
while(cin>>n>>m)
{
vect.clear();
vector<int> tmp;
for(int i=0; i<=n; i++) vect.push_back(tmp);//切忌用resize,会惨死在这

for(int i=0; i<m; i++)
{
scanf("%d%d",&a,&b);
vect[a].push_back(b);
vect[b].push_back(a);
}
if(!is2()&& (puts("No"),1) )    continue; //仅仅为了少一行代码
printf("%d\n",hungary()>>1);    //二分图匹配,匈牙利
}
return 0;
}


AC代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: