题意:
有n个宇航员 他们需要完成A、B、C三种任务 年龄>=平均年龄的人可以做A和C 年龄<平均年龄的能做B和C 且宇航员之间有讨厌关系不能一起做任务 要求给出一种分配方案
思路:
一类人有2种选择而且必须选1个 因此想到2-sat 根据年龄和讨厌关系来建边 之后先做可行性判断 确定可以后 求出任意一组可行解 不需要字典序最小
代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define N 200010 struct edge { int u,v,next; }ed[N*4]; int n,m,tot,top,cnt,idx; int dfn[N],low[N],st[N],instack[N],belong[N],head[N],f[N],col[N],in[N],qu[N],opt[N]; void tarjan(int u) { int i,v; dfn[u]=low[u]=++idx; instack[u]=1; st[++top]=u; for(i=head[u];~i;i=ed[i].next) { v=ed[i].v; if(dfn[v]==-1) { tarjan(v); low[u]=min(low[u],low[v]); } else if(instack[v]&&dfn[v]<low[u]) low[u]=dfn[v]; } if(dfn[u]==low[u]) { cnt++; do { v=st[top--]; instack[v]=0; belong[v]=cnt; }while(u!=v); } } void init() { tot=top=cnt=idx=0; for(int i=0;i<n;i++) { head[i]=-1; dfn[i]=-1; col[i]=0; in[i]=0; } } void add(int u,int v) { ed[tot].u=u; ed[tot].v=v; ed[tot].next=head[u]; head[u]=tot++; } bool can() { int i,u,v; init(); for(i=0;i<m;i++) { scanf("%d%d",&u,&v); u--; v--; u<<=1; v<<=1; if(f[u]==f[v]) { add(u,v^1); add(v,u^1); } add(u^1,v); add(v^1,u); } for(i=0;i<n;i++) { if(dfn[i]==-1) tarjan(i); } for(i=0;i<n;i+=2) { if(belong[i]==belong[i^1]) return false; } return true; } void solve() { int i,u,v,s=tot,l,r; for(i=1;i<=cnt;i++) head[i]=-1; tot=0; for(i=0;i<s;i++) { u=belong[ed[i].u]; v=belong[ed[i].v]; if(u!=v) { add(v,u); in[u]++; } } for(i=0;i<n;i++) opt[belong[i]]=belong[i^1]; l=r=0; for(i=1;i<=cnt;i++) { if(!in[i]) qu[r++]=i; } while(l<r) { u=qu[l++]; if(!col[u]) { col[u]=1; col[opt[u]]=2; } for(i=head[u];~i;i=ed[i].next) { v=ed[i].v; in[v]--; if(!in[v]) qu[r++]=v; } } } int main() { int i,sum; double tmp; while(~scanf("%d%d",&n,&m)) { if(!n&&!m) break; sum=0; n<<=1; for(i=0;i<n;i+=2) { scanf("%d",&f[i]); sum+=f[i]; } tmp=(double)(sum)/(n>>1); for(i=0;i<n;i+=2) { if(fabs(tmp-f[i])<1e-8||f[i]>tmp) f[i]=1; else f[i]=2; f[i+1]=3; } if(can()) { solve(); for(i=0;i<n;i+=2) { if(col[belong[i]]==1) { if(f[i]==1) puts("A"); else puts("B"); } else puts("C"); } } else puts("No solution."); } return 0; }
时间: 2024-10-04 18:02:24