题解 UVA12083 【Guardian of Decency】
二分图最大匹配
这道题最大的难度在于预处理出无向图
前排兜售小广告
题目翻译:
Frank N. Stein是一位非常保守的高中老师。他想带一些学生参加
游览,但他担心他们中的一些人可能成为夫妻。虽然你永远不能排除这一点
可能性,他已经制定了一些规则,他认为这表明两个人的概率很低
一对夫妇:
•它们的高度相差超过40厘米。
•他们属于同一性别。
•他们喜欢的音乐风格不同。
•他们最喜欢的运动是相同的(他们很可能是不同球队的球迷,那会是
导致战斗)。
因此,对于他带来短途旅行的任何两个人,他们必须至少满足其中一个
以上要求。鉴于他们至关重要,帮助他找到他可以承受的最多人数
信息。
输入
输入的第一行包含一个整数T≤100,给出了测试用例的数量。第一行
每个测试用例包含一个N≤500的整数,给出学生的数量。接下来会有一个
每个学生的行由四个以空格分隔的数据项组成:
•整数h,以cm为单位给出高度;
•女性角色'F'或男性角色'M';
•描述首选音乐风格的字符串;
•带有喜爱运动名称的字符串。
输入中的字符串不会包含超过100个字符,任何字符串也不会包含任何字符串
空白。
这里预处理时使用string里的compare
compare使用示例:
std::string str1 ("green apple");
std::string str2 ("red apple");
if (str1.compare(str2) != 0)
std::cout << str1 << " is not " << str2 << '\n';
if (str1.compare(6,5,"apple") == 0)//第一个参数表示str1中的位置:str1[6],第二个参数表示要比较的字符串的最大数量,即从指定位置开始后的比较数目
std::cout << "still, " << str1 << " is an apple\n";
if (str2.compare(str2.size()-5,5,"apple") == 0)//同上
std::cout << "and " << str2 << " is also an apple\n";
if (str1.compare(6,5,str2,4,5) == 0)//str1中的“apple”和str2中的“apple”比较
std::cout << "therefore, both are apples\n"
预处理完 跑一个最大匹配即可 (不会右转二分图匹配)
ac代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=100001;
struct node//链式前向星
{
int v;
int next;
}G[MAXN];
int head[MAXN];
int cnt;
struct stu
{
int h;
char sex;
string musics;
string sports;
stu(){sports = musics = "12213124142";}
}stu[MAXN];
int num=0;
void add(int u,int v)//加边
{
G[++cnt].v=v;
G[cnt].next=head[u];
head[u]=cnt;
}
int result[MAXN];
bool vis[MAXN];
int ans;
int find(int p)//最大匹配
{
for(int i=head[p];i;i=G[i].next)
{
int to=G[i].v;;
if(!vis[to])
{
vis[to]=true;
if(!result[to])
{
result[p]=to;
result[to]=p;
return 1;
}
else if(find(result[to]))
{
result[p]=to;
result[to]=p;
return 1;
}
}
}
return 0;
}
bool music(int i,int j)
{
int ans=stu[i].musics.compare(1,stu[i].musics.length(),stu[j].musics,1,stu[j].musics.length());
if(ans==0) return true;
else return false;
}
bool sports(int i,int j)
{
int ans=stu[i].sports.compare(1,stu[i].sports.length(),stu[j].sports,1,stu[j].sports.length());
if(ans==0) return false;
else return true;
}
int main()
{
int t;
cin>>t;
while(t--)
{
memset(G,0,sizeof(G));
memset(head,0,sizeof(head));
cnt=0;
memset(result,0,sizeof(result));
num=0;
ans=0;
cin>>num;
for(int i=1;i<=num;i++)
{
cin>>stu[i].h;
cin>>stu[i].sex;
cin>>stu[i].musics;
cin>>stu[i].sports;
for(int j=1;j<i;j++)
{
if((-40<=stu[i].h-stu[j].h && stu[i].h-stu[j].h<=40) && stu[i].sex!=stu[j].sex && sports(i,j)&&music(i,j))
{
add(i,j);
add(j,i);
}
}
}
for(int i=1;i<=num;i++)
{
if(!result[i])
{
memset(vis,0,sizeof(vis));
ans+=find(i);
}
}
cout<<num-ans<<endl;
for(int i=1;i<=num;i++)//不要忘记清零
{
stu[i].sex=' ';
stu[i].h=0;
stu[i].musics.clear();
stu[i].sports.clear();
}
}
return 0;
}