2-SAT,复杂度是O(m),每个点分成2个点,代表选或者不选,然后建图有个原则,就是一条有向边x->y代表x选了y必选,然后建图完tarjan,如果有2个点在同一个环中,无解,否则建立反向图拓扑排序,搜到一个点,就把他对立点和后继全部选为不选。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<vector> 7 int tot,go[200005],first[200005],next[200005]; 8 int instack[200005],num,sz,low[200005],dfn[200005]; 9 int vis[200005],st[200005],top; 10 int c[200005],belong[200005],n,m,ru[200005],op[200005],col[200005]; 11 std::vector<int> son[200005]; 12 int read(){ 13 int t=0,f=1;char ch=getchar(); 14 while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘)f=-1;ch=getchar();} 15 while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();} 16 return t*f; 17 } 18 void insert(int x,int y){ 19 tot++; 20 go[tot]=y; 21 next[tot]=first[x]; 22 first[x]=tot; 23 } 24 void tarjan(int x){ 25 instack[x]=1;low[x]=dfn[x]=++sz; 26 vis[x]=1;st[++top]=x; 27 for (int i=first[x];i;i=next[i]){ 28 int pur=go[i]; 29 if (!vis[pur]){ 30 tarjan(pur); 31 low[x]=std::min(low[x],low[pur]); 32 }else if (instack[pur]){ 33 low[x]=std::min(low[x],dfn[pur]); 34 } 35 } 36 if (low[x]==dfn[x]){ 37 num++; 38 while (st[top]!=x){ 39 instack[st[top]]=0; 40 belong[st[top]]=num; 41 top--; 42 } 43 instack[x]=0; 44 belong[x]=num; 45 top--; 46 } 47 } 48 void dfs(int x){ 49 if (col[x]) return;col[x]=-1; 50 for (int i=0;i<son[x].size();i++){ 51 dfs(son[x][i]); 52 } 53 } 54 void solve(){ 55 int t=0; 56 for (int i=1;i<=num;i++) if (!ru[i]) c[++t]=i; 57 while (t){ 58 int now=c[t--]; 59 if (col[now]) continue; 60 col[now]=1; 61 dfs(op[now]); 62 for (int i=0;i<son[now].size();i++){ 63 if (!(--ru[son[now][i]])) c[++t]=son[now][i]; 64 } 65 } 66 } 67 int main(){ 68 freopen("gates.in","r",stdin); 69 freopen("gates.out","w",stdout); 70 n=read();m=read(); 71 for (int i=1;i<=n;i++){ 72 int a=read(),sa=read(),b=read(),sb=read(); 73 if (sa==0){ 74 if (sb==0) insert(a<<1,(b<<1)-1),insert(b<<1,(a<<1)-1); 75 else insert(a<<1,b<<1),insert((b<<1)-1,(a<<1)-1); 76 }else{ 77 if (sb==0) insert((a<<1)-1,(b<<1)-1),insert(b<<1,a<<1); 78 else insert((a<<1)-1,b<<1),insert((b<<1)-1,a<<1); 79 } 80 } 81 for (int i=1;i<=m<<1;i++) if (!vis[i]) tarjan(i); 82 for (int i=1;i<=m;i++) 83 if (belong[(i<<1)-1]==belong[i<<1]){ 84 puts("IMPOSSIBLE"); 85 return 0; 86 } 87 for (int i=1;i<=m<<1;i++) 88 for (int j=first[i];j;j=next[j]){ 89 int pur=go[j]; 90 if (belong[pur]==belong[i]) continue; 91 son[belong[pur]].push_back(belong[i]); 92 ru[belong[i]]++; 93 } 94 for (int i=1;i<=m;i++) 95 op[belong[i<<1]]=belong[(i<<1)-1],op[belong[(i<<1)-1]]=belong[i<<1]; 96 solve(); 97 for (int i=1;i<=m;i++) if (col[belong[i<<1]]==1) puts("1");else puts("0"); 98 }
时间: 2024-10-26 13:57:30