UVALive-3713 Astronauts (2-SAT)
题目大意:有三个任务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; }