题意在大白书上。
有3 种工作 abc 大于等于平均年龄的可以去做a c 工作, 小于平均年龄的可以去做 bc , 同样转化为2 -sat 去做, 因为对于每个人也只有2 种情况可以作为选择
#include <iostream> #include <algorithm> #include <string.h> #include <cstdio> #include <vector> using namespace std; const int maxn=100000+10; struct TwoSAT{ int n; vector<int > G[maxn*2]; bool mark[maxn*2]; int S[maxn*2],c; bool dfs(int x){ if(mark[x^1]) return false; if(mark[x]) return true; mark[x]=true; S[c++]=x; for(int i=0; i<G[x].size(); i++) if(!dfs(G[x][i])) return false; return true; } void inti(int n){ this->n =n; for(int i=0; i<2*n; ++i) G[i].clear(); memset(mark,0,sizeof(mark)); } void add_clause(int x, int xval, int y, int yval){ x = x * 2 + xval; y = y * 2 + yval; G[x^1].push_back(y); G[y^1].push_back(x); } bool solve(){ for(int i=0; i<n*2; i+=2 ) if(!mark[i] && !mark[i+1]){ c=0; if(!dfs(i)){ while(c>0) mark[ S[ --c ] ] = false; if(!dfs(i+1)) return false; } } return true; } }solver; int n,m,total_age; int age[maxn]; bool isyoung(int x){ return x*n<total_age; } int main() { while(scanf("%d%d",&n,&m)==2&&n){ total_age=0; for(int i=0; i<n; ++i){ scanf("%d",&age[i]); total_age+=age[i]; } solver.inti(n); for(int i=0; i<m; ++i){ int u,v; scanf("%d%d",&u,&v); u--; v--; if(u==v)continue; solver.add_clause(u, 1 , v , 1); if(isyoung(age[u])==isyoung(age[v])){ solver.add_clause( u, 0 , v ,0 ); } } if(!solver.solve()) printf("No solution. "); else { for(int i=0; i<n; i++) if(solver.mark[i*2]) printf("C "); else if(isyoung(age[i])) printf("B "); else printf("A "); } } return 0; }