http://codeforces.com/contest/245/problem/D
和今年长春赛区的 第二题一样 2-sat 将每一个数的每一位作为一个点 要么是 1 要么是 0
2-sat 主要是代码长 比较繁琐 尤其是需要求结果的题目
-----------不对劲呀 走在路上一想 这个题不用2—sat 就可以呀 晕 想多了 附加简单代码
代码1:
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<set> #include<map> #include<string> #include<queue> #include<stack> #include <iomanip> using namespace std; #define LL long long const int INF=0x3f3f3f3f; const int N=102*31*2; int head[N],I; struct node { int j,next; }side[N*N/4]; int low[N],dfn[N],f[N],deep; bool in[N],visited[N]; stack<int>st; queue<int>qt; vector<int>tree[N]; int sum[N]; int color[N]; int a[103],b[103][103]; void add(int i,int j) { side[I].j=j; side[I].next=head[i]; head[i]=I++; } void Tarjan(int x) { visited[x]=true; in[x]=true; st.push(x); low[x]=dfn[x]=deep++; for(int t=head[x];t!=-1;t=side[t].next) { int j=side[t].j; if(!visited[j]) { Tarjan(j); low[x]=min(low[x],low[j]); }else if(in[j]) { low[x]=min(low[x],dfn[j]); } } if(low[x]==dfn[x]) { while(st.top()!=x) { in[st.top()]=false; f[st.top()]=x; st.pop(); } in[st.top()]=false; f[st.top()]=x; st.pop(); } } void buildtree(int m) { for(int i=0;i<2*m;++i) tree[i].clear(); memset(sum,0,sizeof(sum)); for(int i=0;i<2*m;++i) if(f[i]==i) { for(int t=head[i];t!=-1;t=side[t].next) { int j=side[t].j; if(f[j]==j) { tree[j].push_back(i); ++sum[i]; } } } } void decside(int x) { for(unsigned int i=0;i<tree[x].size();++i) { --sum[tree[x][i]]; if(sum[tree[x][i]]==0) { qt.push(tree[x][i]); } } } void topo(int m) { memset(color,0,sizeof(color)); for(int i=0;i<2*m;++i) { if(sum[i]==0) qt.push(i); } while(!qt.empty()) { int x=qt.front();qt.pop(); if(color[x]!=0) continue; color[x]=1; int y=(x<m)?x+m:x-m; color[y]=-1; decside(x); decside(y); } } int main() { //freopen("data.in","r",stdin); int n; while(cin>>n) { for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) cin>>b[i][j]; if(n==1) {cout<<"0"<<endl;continue;} int m=n*31; memset(head,-1,sizeof(head)); I=0; for(int i=1;i<=n;++i) { for(int j=i+1;j<=n;++j) { for(int x=0;x<31;++x) { int l=(i-1)*31+x; int r=(j-1)*31+x; if(b[i][j]&(1<<x)) { add(l+m,l); add(r+m,r); }else { add(l,r+m); add(r,l+m); } } } } memset(visited,false,sizeof(visited)); memset(in,false,sizeof(in)); deep=0; for(int i=0;i<2*m;++i) { if(!visited[i]) Tarjan(i); } buildtree(m); topo(m); memset(a,0,sizeof(a)); for(int i=0;i<m;i=i+31) { for(int j=0;j<31;++j) { if(color[f[i+j]]==1) a[i/31+1]=(a[i/31+1]|(1<<j)); } } for(int i=1;i<=n;++i) { if(i>1) cout<<" "; cout<<a[i]; } cout<<endl; } return 0; }
代码2:
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<set> #include<map> #include<string> #include<queue> #include<stack> #include <iomanip> using namespace std; #define LL long long const int INF=0x3f3f3f3f; const int N=105; int a[N],b[N][N]; int main() { //freopen("data.in","r",stdin); int n; while(cin>>n) { memset(a,0,sizeof(0)); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) { cin>>b[i][j]; if(i==j) continue; for(int l=0;l<31;++l) { if(b[i][j]&(1<<l)) { a[i]=a[i]|(1<<l); a[j]=a[j]|(1<<l); } } } for(int i=1;i<=n;++i) { if(i>1) cout<<" "; cout<<a[i]; } cout<<endl; } return 0; }