输出方案采用了刘大师的写法,直接给每个强连通分量标号,每个人只要选属于较小编号的点即可。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n,m,ss,w_time,top,bj;
int tail[500000],next[2000000],sora[2000000];
int rel[500000],low[500000],st[500000],v[500000],b[500000],col[500000];
int age[500000],rank[500000];
void origin()
{
ss=n+n;
for (int i=1;i<=n+n;i++) tail[i]=i,next[i]=0;
for (int i=1;i<=n+n;i++)
rel[i]=low[i]=v[i]=0,b[i]=i,col[i]=0;
w_time=0,top=0;
bj=0;
}
void link(int x,int y)
{
++ss,next[tail[x]]=ss,tail[x]=ss,sora[ss]=y,next[ss]=0;
}
void dfs(int x)
{
w_time++;
rel[x]=low[x]=w_time;
st[++top]=x,v[x]=1;
for (int i=x,ne;next[i];) {
i=next[i],ne=sora[i];
if (!v[ne]) {
dfs(ne);
low[x]=min(low[x],low[ne]);
}
else
if (v[ne]==1) low[x]=min(low[x],rel[ne]);
}
if (low[x]==rel[x]) {
for (;st[top]!=x;top--) {
int ne=st[top];
b[ne]=x,v[ne]=2;
}
top--;
b[x]=x,v[x]=2;
col[x]=++bj;
}
}
int main()
{
freopen("input.txt","r",stdin);
for (;scanf("%d%d",&n,&m)==2;) {
origin();
int tot=0;
for (int i=1;i<=n;i++) {
scanf("%d",&age[i]);
tot+=age[i];
}
for (int i=1;i<=n;i++)
rank[i]=(age[i]*n>=tot);
for (int i=1;i<=m;i++) {
int x,y;
scanf("%d%d",&x,&y);
if (rank[x]!=rank[y]) {
link(x+n,y);
link(y+n,x);
}
else {
link(x,y+n);
link(y,x+n);
link(x+n,y);
link(y+n,x);
}
}
for (int i=1;i<=n+n;i++)
if (!v[i]) dfs(i);
bool flag=1;
for (int i=1;i<=n;i++)
if (b[i]==b[i+n]) {
flag=0;
break;
}
if (!flag) {
printf("No solution.\n");
continue;
}
for (int i=1;i<=n;i++)
if (col[b[i]]<col[b[i+n]]) {
if (rank[i]) printf("A\n");
else printf("B\n");
}
else {
printf("C\n");
}
}
return 0;
}