C - Guardian of Decency UVA - 12083--二分图匹配+最大独立集( |最大独立集| = |V|-|最大匹配数|)
2017-08-22 09:17
447 查看
题目大意:Frank是一个思想有些保守的老师。有一次,他需要带一些学生出去旅游,但又怕其中有一些学生在旅途中萌生爱意。为了降低这种事情发生的概率,他决定确保带出去的任意两个学生至少要满足下面4条中的一条:
1)身高相差大于40厘米。
2)性别相同。
3)最喜欢的音乐属于不同的类型。
4)最喜欢的体育比赛相同。
你的任务是帮助Frank挑选尽量多的学生,使得任意两个学生至少满足上述条件中的一条。
PS:简单来说就是有N个人,已知身高、性别、音乐、运动。要求选出尽可能多的人,使这些人两两之间至少满足四个条件之一。
思路:第一次做二分图匹配,也是看了题解才知道的这个板子,但本题不是单纯的用二分图匹配,这也就导致一开始只按照二分图匹配的应用思路来看并不符合本题的思路。本题要求的是两两互相不能组合的最大独立集体(最大独立集:顶点集V中取 K个顶点,其两两间无连接),有公式知:(|最大独立集| = |V|-|最大匹配数|)。所以在用二分图匹配求出最大匹配数后,还要运用公式求出最大独立集,最大独立集才是本题所求。
AC代码:
#include <iostream>
#include <cstdio>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
using namespace std;
int v[501];
int line[501];
int n;
typedef struct pp
{
public:
int h;
char s;
string m;
string sp;
};
pp p[501];
bool panduan(pp a,pp b)
{
if(fabs(a.h-b.h)>40||a.m!=b.m||a.s==b.s||a.sp==b.sp)
return false;
return true;
}
bool judge(int x)
{
for(int i=0;i<n;i++)
{
if(!v[i]&&i!=x)
{
if(panduan(p[i],p[x]))
{
v[i]=1;
if(line[i]==0||judge(line[i]))
{
line[i]=x;
//line[x]=i;
return 1;
}
}
}
}
return 0;
}
int main()
{
int t,m;
scanf("%d",&t);
while(t--)
{
memset(line,0,sizeof(line));
int ans=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
cin>>p[i].h;
cin>>p[i].s;
cin>>p[i].m;
cin>>p[i].sp;
}
for(int i=0;i<n;i++)
{ memset(v,0,sizeof(v));
if(judge(i))
ans++;
}
cout<<n-ans<<endl;
}
}
另外摘抄网上的一份代码,该代码算然长一点,但是更好理解:
#include<cstdio>
#include<cstring>
#include<map>
#include<cstdlib>
#include<string>
using namespace std;
struct node
{
int h,music,sport;
}man[510],woman[510];
int T,t,n,m,num_man,num_woman,tot,link[510][510];
char s[110];
map<string,int> match;
bool vis[510];
int mat[510];
int getnum()
{
int k=match[s];
if(k!=0)
return k;
match[s]=++tot;
return tot;
}
bool dfs(int u)
{
int i,j,k;
for(i=1;i<=num_woman;i++)
if(link[u][i] && !vis[i])
{
vis[i]=1;
if(mat[i]==0 || dfs(mat[i]))
{
mat[i]=u;
return true;
}
}
return false;
}
int main()
{
int i,j,k,h,music,sport,ans;
scanf("%d",&T);
for(t=1;t<=T;t++)
{
scanf("%d",&n);
num_man=num_woman=tot=0;
match.clear();
for(i=1;i<=n;i++)
{
scanf("%d",&h);
scanf("%s",s);
if(s[0]=='M')
k=0;
else
k=1;
scanf("%s",s);music=getnum();
scanf("%s",s);sport=getnum();
if(k==0)
{
num_man++;
man[num_man].h=h;
man[num_man].music=music;
man[num_man].sport=sport;
}
else
{
num_woman++;
woman[num_woman].h=h;
woman[num_woman].music=music;
woman[num_woman].sport=sport;
}
}
memset(link,0,sizeof(link));
for(i=1;i<=num_man;i++)
for(j=1;j<=num_woman;j++)
if(abs(man[i].h-woman[j].h)>40 || man[i].music!=woman[j].music || man[i].sport==woman[j].sport)
link[i][j]=0;
else
link[i][j]=1;
ans=0;
memset(mat,0,sizeof(mat));
for(i=1;i<=num_man;i++)
{
memset(vis,0,sizeof(vis));
if(dfs(i))
ans++;
}
printf("%d\n",n-ans);
}
}
PS:求解最大独立集两种方法,本题使用二分图匹配法,另外是应用最大团(最大团中顶点数量
= 补图的最大独立集中顶点数量)POJ1419即该法的直接应用,而且该题无法运用二分图匹配法。
相关文章推荐
- UVA 12083 Guardian of Decency(最大独立集)
- UVA - 12083 Guardian of Decency 匈牙利算法(二分图最大匹配)
- UVA 12083 - Guardian of Decency(二分图最大匹配)
- UVA-12083 Guardian of Decency 二分图 最大独立集
- Guardian of Decency UVALive - 3415 最大独立集=结点数-最大匹配数 老师带大学生旅游
- UVA - 12083 Guardian of Decency (匈牙利算法 求 最大独立集)
- la 3415, 12083 - Guardian of Decency 最大匹配,独立集,覆盖集
- UVALive 3415 Guardian of Decency(二分图的最大独立集)
- Guardian of Decency UVA - 12083 (二分匹配)
- UVALive 3415 Guardian of Decency(二分图最大独立集)
- UVALive-3415 Guardian of Decency (最大独立集)
- Guardian of Decency - UVa 12083 二分图最大独立点集
- POJ2771_Guardian of Decency(二分图/最大独立集=N-最大匹配)
- UVAlive3415 Guardian of Decency(最大独立集)
- UVALive3415[Guardian of Decency] 二分图最大独立集模型
- uva 12083 Guardian of Decency (二分图匹配)
- POJ 2771 Guardian of Decency(最大独立集、二分图匹配)
- poj2771——Guardian of Decency——————【最大独立集、最大匹配扩展】
- poj2771 Guardian of Decency 二分匹配之最大独立集
- uva 12083 - Guardian of Decency(二分图匹配)