题目大意:有三个任务A、B、C,n个已知年龄的人。A任务只能被年龄不小于平均年龄的人做,B任务只能被平均年龄以下的人做,C任务不限,相互讨厌的两个人不能做同一件任务,现在已知厌恶关系,求一种任务分配方案。
题目分析:每个人都有两个选择,对于年龄大的人,设选A为真,选C为假,对年龄小的人,设选B为真,选C为假。相互讨厌的两个人X、Y若同类,X、Y只能一真一假,也就是X、Y不能同真也不能同假,连边:X1->Y0、Y1->X0、X0->Y1、Y0->X1;若X、Y不是同类,则X、Y不能同时为假,连边:X0->Y1、Y0->X1。
代码如下:
# include<iostream>
# include<cstdio>
# include<vector>
# include<cstring>
# include<algorithm>
using namespace std;
const int maxn=100005;
vector<int>G[2*maxn];
int mark[2*maxn],Age[maxn],S[maxn],cnt;
double x;
bool same(int a,int b)
{
if(Age[a]>=x&&Age[b]>=x)
return true;
if(Age[a]<x&&Age[b]<x)
return true;
return false;
}
bool dfs(int u)
{
if(mark[u^1]) return false;
if(mark[u]) return true;
mark[u]=1;
S[cnt++]=u;
for(int i=0;i<G[u].size();++i)
if(!dfs(G[u][i]))
return false;
return true;
}
bool judge(int n)
{
memset(mark,0,sizeof(mark));
for(int i=0;i<2*n;i+=2){
cnt=0;
if(!dfs(i)){
while(cnt>0) mark[S[--cnt]]=0;
if(!dfs(i+1)) return false;
}
}
return true;
}
int main()
{
int n,m,a,b;
while(scanf("%d%d",&n,&m)&&(n+m))
{
for(int i=0;i<2*n;++i) G[i].clear();
x=0.0;
for(int i=0;i<n;++i){
scanf("%d",Age+i);
x+=Age[i];
}
x/=n;
while(m--)
{
scanf("%d%d",&a,&b);
--a,--b;
G[2*a+1].push_back(2*b);
G[2*b+1].push_back(2*a);
if(same(a,b)){
G[2*a].push_back(2*b+1);
G[2*b].push_back(2*a+1);
}
}
if(!judge(n))
printf("No solution.\n");
else for(int i=0;i<2*n;i+=2){
if(!mark[i])
printf("C\n");
else
printf("%c\n",(Age[i/2]>=x)?'A':'B');
}
}
return 0;
}