题意:
有N个宇航员要登录星球..大于等于平均年龄的宇航员是老宇航员...后则是小宇航员...老宇航员能登陆A,C星球..小宇航员能登录B,C星球..而有些对宇航员间有矛盾..不能登录同一个星球...请找出任意可行的一种登陆方案...
题解:
由于老宇航员和小宇航员都共有C...那么首先看作两个状态..登陆C或者不登陆C..所以对于一对敌对关系<a,b>有
1、当a登陆c时..b不能登陆c...b登录c时a不能登录c...这样可以构造两条有向边
2、当a,b是同一年龄段的..那么当a不登陆c时..b一定要登陆c...b不登录c时..a一定又登陆c...这样在条件下再构造两条有向边...
然后就跑tarjan..判断可行性并且缩点..然后用toposort找出一组可行解...输出的时候..当老宇航员是非C时输出A..小宇航员非C时输出B..不论大小..是C时输出C...
这道题更新了toposort的过程..总算不是那么有漏洞和暴力了...思想是缩点后构造反向边...然后从反向边的图中入度为0的点开始标记(也就是原图中出度为0的点)...标记的过程中...将它自己标记成"拿"..将与其相斥的点染成"不拿"...这里很有意思..对于一个缩了的点..我是以为它会有多个冲突的点..但是实践证明它只有至多一个相互冲突的点..那直接用个数组存下其标号就行了...
Program:
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<stack>
#include<string.h>
#include<map>
#include<set>
#include<algorithm>
#define oo 1000000007
#define MAXN 100005<<1
#define MAXM 100000<<2
#define ll long long
using namespace std;
struct node
{
int x,y,next;
}line[MAXM];
int Lnum,_next[MAXN],age[MAXN],dfn[MAXN],low[MAXN],tp[MAXN],tpnum,DfsIndex;
int color[MAXN],d[MAXN],opp[MAXN];
bool old[MAXN],instack[MAXN];
set<int> T[MAXN];
stack<int> mystack;
queue<int> myqueue;
void addline(int x,int y)
{
line[++Lnum].next=_next[x],_next[x]=Lnum;
line[Lnum].x=x,line[Lnum].y=y;
}
void tarjan(int x)
{
instack[x]=true,mystack.push(x);
dfn[x]=low[x]=++DfsIndex;
for (int k=_next[x];k;k=line[k].next)
{
int y=line[k].y;
if (!dfn[y])
{
tarjan(y);
low[x]=min(low[x],low[y]);
}else
if (instack[y])
low[x]=min(low[x],dfn[y]);
}
if (low[x]==dfn[x])
{
tpnum++;
do
{
x=mystack.top();
mystack.pop();
instack[x]=true;
tp[x]=tpnum;
}while (low[x]!=dfn[x]);
}
}
bool judge(int N)
{
for (int i=0;i<N;i++)
if (tp[i<<1]==tp[i<<1|1]) return false;
return true;
}
void toposort(int N)
{
int i,h;
memset(color,0,sizeof(color));
while (!myqueue.empty()) myqueue.pop();
for (i=1;i<=N;i++)
if (!d[i]) myqueue.push(i);
while (!myqueue.empty())
{
h=myqueue.front();
myqueue.pop();
if (color[h]) continue;
color[h]=1,color[opp[h]]=2;
set<int>::iterator it;
for (it=T[h].begin();it!=T[h].end();it++)
{
d[*it]--;
if (!d[*it]) myqueue.push(*it);
}
}
}
int main()
{
int N,M,i,sum,v;
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
while (~scanf("%d%d",&N,&M) && (N || M))
{
sum=0;
for (i=0;i<N;i++) scanf("%d",&age[i]),sum+=age[i];
Lnum=0,memset(_next,0,sizeof(_next));
v=(int)(sum*1.0/N);
if (v*N<sum) v++;
memset(old,false,sizeof(old));
for (i=0;i<N;i++)
if (age[i]>=v)
old[i]=true;
while (M--)
{
int x,y;
scanf("%d%d",&x,&y);
addline(x<<1,y<<1|1),addline(y<<1,x<<1|1); //x<<1选c...x<<1|1不选
if (old[x]^old[y]==0)
addline(x<<1|1,y<<1),addline(y<<1|1,x<<1);
}
memset(dfn,0,sizeof(dfn));
memset(instack,false,sizeof(instack));
while (!mystack.empty()) mystack.pop();
tpnum=DfsIndex=0;
for (i=0;i<(N<<1);i++)
if (!dfn[i]) tarjan(i);
if (!judge(N))
{
printf("No solution.\n");
continue;
}
for (i=1;i<=tpnum;i++) T[i].clear();
for (i=0;i<(N<<1);i++) opp[tp[i]]=tp[i^1];
memset(d,0,sizeof(d));
for (i=1;i<=Lnum;i++)
{
int x=tp[line[i].x],y=tp[line[i].y];
if (x==y || T[y].count(x)) continue;
T[y].insert(x); d[x]++;
}
toposort(tpnum);
for (i=0;i<N;i++)
{
if (color[tp[i<<1]]==1) printf("C\n");
else
if (old[i]) printf("A\n");
else printf("B\n");
}
}
return 0;
}