题意: 参加一个会议:其中的某些人参加不参加,有如下关系:
1 x y 表示两人两个人至少去一个;
2 x y 表示x 不去,y也不能去>>>>>>>>>>>>>可以推出 y去了x也肯定去了。。。错了n次, 无语了。
3 x y 表示两个人至少一个不去
4 x y 表示两个人只能去一个,不能少
1 x y z 三个人至少去一个
2 x y z 三个人至少一个不去
思路:三个人有关系的枚举所有情况,3^5 其余的用2-sat
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <stack> #include <map> #include <iostream> using namespace std; const int N = 2019; int n,m,k; int re1[N][3]; int re2[9][4]; struct LT{ int nex,to; } L[90009],EL[90009]; int EF[N],Ecnt; int F[N],cnt; void add(int f,int t) { L[cnt].nex = F[f]; L[cnt].to = t; F[f] = cnt++; } void Eadd(int f,int t) { EL[Ecnt].nex =EF[f]; EL[Ecnt].to = t; EF[f] = Ecnt++; } int dfn[N],low[N],post[N],col[N],color,ind; stack<int>S; void tarjan(int k) { dfn[k] = low[k] = ind++; post[k] = 1;S.push(k); for(int i=F[k];i;i=L[i].nex) { int to = L[i].to; if(!dfn[to]) { tarjan(to); low[k] = min(low[k],low[to]); } else if(post[to]&&dfn[to]<low[k]) low[k] = dfn[to]; } if(low[k]==dfn[k]) { color++;int i; for(i=S.top(),S.pop();i!=k;i=S.top(),S.pop()) { post[i] = 0,col[i] = color; Eadd(color,i); } post[k]=0,col[k]=color; Eadd(color,k); } } bool judge() { for(int i=0;i<n;i++) if(col[i]==col[i+n]) return false; return true; } int ans[N],v[N]; void out() { memset(v,-1,sizeof(v)); for(int i=1;i<=color;i++) if(v[i]==-1) { for(int j=EF[i];j;j=EL[j].nex) { v[col[(EL[j].to+n)%(n<<1)]] = 1; }v[i]=0; } int coun = 0; for(int i=0;i<n;i++) if(v[col[i]]==0) ans[coun++] = i+1; printf(" %d",coun); for(int i=0;i<coun;i++) printf(" %d",ans[i]); printf(".\n"); } void solve() { int cas = (int)pow(3.0,k); for(int cc = 0;cc<cas;cc++) { int c=cc; memset(F,0,sizeof(F));cnt=1; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low));ind = 1; memset(EF,0,sizeof(EF));Ecnt = 1; color = 0; for(int i=0;i<k;i++) { int a=c%3; c/=3; int t = re2[i][a+1]; if(re2[i][0]==1) { add(t+n,t); }else{ add(t,t+n); } } for(int i=0;i<m;i++) { if(re1[i][0]==1) { add(re1[i][1]+n,re1[i][2]); add(re1[i][2]+n,re1[i][1]); }else if(re1[i][0]==2) { //cout<<" -- "<<re1[i][1]<<" "<<re1[i][2]<<endl; add(re1[i][1]+n,re1[i][2]+n); add(re1[i][2],re1[i][1]); }else if(re1[i][0]==3) { add(re1[i][1],re1[i][2]+n); add(re1[i][2],re1[i][1]+n); }else { add(re1[i][1],re1[i][2]+n); add(re1[i][1]+n,re1[i][2]); add(re1[i][2],re1[i][1]+n); add(re1[i][2]+n,re1[i][1]); } } for(int i=0;i<(n<<1);i++) if(!dfn[i]) tarjan(i); if(judge()) { cout<<"Possible"; out(); return ; } } cout<<"Impossible."<<endl; } int main() { freopen("in.txt","r",stdin); int cas,T=1; scanf("%d",&cas); while(cas--) { scanf("%d%d%d",&n,&m,&k); for(int i=0;i<m;i++) scanf("%d%d%d",&re1[i][0],&re1[i][1],&re1[i][2]); for(int i=0;i<m;i++) re1[i][1]-=1,re1[i][2]-=1; for(int i=0;i<k;i++) scanf("%d%d%d%d",&re2[i][0],&re2[i][1],&re2[i][2],&re2[i][3]); for(int i=0;i<k;i++) re2[i][1]-=1,re2[i][2]-=1,re2[i][3]-=1; printf("Case %d: ",T++); solve(); } return 0; }