【2-sat】uva1391

来源:互联网 发布:手机编写javascript 编辑:程序博客网 时间:2024/05/21 12:43

输出方案采用了刘大师的写法,直接给每个强连通分量标号,每个人只要选属于较小编号的点即可。

#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;}


0 0
原创粉丝点击