SGU 307 Cipher(2-SAT)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=307

题意:N*M的01矩阵 A,(N-1)*(M-1)的矩阵B,其中B[i][j]=A[i][j]+A[i+1][j]+A[i][j+1]+A[i+1][j+1].给出B输出A。

思路:

SGU 307 Cipher(2-SAT)_第1张图片

这样,对于a[i][j](1<=i<=n-1,1<=j<=m-1),只是由a[n][m],a[n][j]和a[i][m]所限制。因此,枚举a[n][m],接着根据a[n][j]和a[i][m]计算出a[i][j],不是1和0时建立2-SAT。

#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <map>
#include <sstream>


#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)>=0?(x):-(x))
#define i64 long long
#define u32 unsigned int
#define u64 unsigned long long
#define clr(x,y) memset(x,y,sizeof(x))
#define CLR(x) x.clear()
#define ph(x) push(x)
#define pb(x) push_back(x)
#define Len(x) x.length()
#define SZ(x) x.size()
#define PI acos(-1.0)
#define sqr(x) ((x)*(x))

#define FOR0(i,x) for(i=0;i<x;i++)
#define FOR1(i,x) for(i=1;i<=x;i++)
#define FOR(i,a,b) for(i=a;i<=b;i++)
#define DOW0(i,x) for(i=x;i>=0;i--)
#define DOW1(i,x) for(i=x;i>=1;i--)
#define DOW(i,a,b) for(i=a;i>=b;i--)
using namespace std;


void RD(int &x){scanf("%d",&x);}
void RD(i64 &x){scanf("%I64d",&x);}
void RD(u32 &x){scanf("%u",&x);}
void RD(double &x){scanf("%lf",&x);}
void RD(int &x,int &y){scanf("%d%d",&x,&y);}
void RD(i64 &x,i64 &y){scanf("%I64d%I64d",&x,&y);}
void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}
void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}
void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}
void RD(i64 &x,i64 &y,i64 &z){scanf("%I64d%I64d%I64d",&x,&y,&z);}
void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}
void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}
void RD(char &x){x=getchar();}
void RD(char *s){scanf("%s",s);}
void RD(string &s){cin>>s;}


void PR(int x) {printf("%d\n",x);}
void PR(i64 x) {printf("%lld\n",x);}
void PR(u32 x) {printf("%u\n",x);}
void PR(u64 x) {printf("%llu\n",x);}
void PR(double x) {printf("%.4lf\n",x);}
void PR(char x) {printf("%c\n",x);}
void PR(char *x) {printf("%s\n",x);}
void PR(string x) {cout<<x<<endl;}

 struct node
 {
     int v,next;
 };



 const int MAX=1205;
 const int MAXE=1000005;
 node edges[MAXE];
 int head[MAX],e;
 int dfn[MAX],low[MAX],visit[MAX],color[MAX],col[MAX];
 int n,index,cnt;
 stack<int> S;
 int deg[MAX],ans[MAX],p[MAX];
 int head1[MAX],e1;
 node edges1[MAXE];

 int B[MAX][MAX],C[MAX][MAX],A[MAX][MAX],N,M;

 void Add(int u,int v)
 {
     edges[e].v=v;
     edges[e].next=head[u];
     head[u]=e++;
 }

 void Add1(int u,int v)
 {
     edges1[e1].v=v;
     edges1[e1].next=head1[u];
     head1[u]=e1++;
 }

 void Tarjan(int u)
 {
     int i,v;

     low[u]=dfn[u]=++index;S.push(u);visit[u]=1;
     for(i=head[u];i!=-1;i=edges[i].next)
     {
         v=edges[i].v;
         if(!dfn[v])
         {
             Tarjan(v);
             low[u]=min(low[u],low[v]);
         }
         else if(visit[v]) low[u]=min(low[u],dfn[v]);
     }
     if(dfn[u]==low[u])
     {
         cnt++;
         do
         {
             v=S.top();
             S.pop();
             visit[v]=0;
             color[v]=cnt;
         }while(u!=v);
     }
 }

 void init()
 {
     memset(deg,0,sizeof(deg));
     memset(head1,-1,sizeof(head1));
     e1=0;
     int i,u,v,x,y;
     for(u=1;u<=2*n;u++)
     {
         for(i=head[u];i!=-1;i=edges[i].next)
         {
             v=edges[i].v;
             if(color[v]!=color[u])
             {
                 x=color[v];
                 y=color[u];
                 Add1(x,y);
                 deg[y]++;
             }
         }
     }
     while(!S.empty()) S.pop();
     for(i=1;i<=cnt;i++) if(!deg[i]) S.push(i);
     memset(p,0,sizeof(p));
     while(!S.empty())
     {
         u=S.top();
         S.pop();
         if(!p[u]) p[u]=1,p[col[u]]=-1;
         for(i=head1[u];i!=-1;i=edges1[i].next)
         {
             v=edges1[i].v;
             if(--deg[v]==0) S.push(v);
         }
     }
 }

 int TWO_ST()
 {
     int i;

     memset(dfn,0,sizeof(dfn));
     memset(visit,0,sizeof(visit));
     index=cnt=0;
     while(!S.empty()) S.pop();
     for(i=1;i<=2*n;i++) if(!dfn[i]) Tarjan(i);
     for(i=1;i<=n;i++)
     {
         if(color[i*2-1]==color[i*2]) return 0;
         col[color[i*2-1]]=color[i*2];
         col[color[i*2]]=color[i*2-1];
     }
     init();
     return 1;
 }


 int ok(int x)
 {
     return x==0||x==1;
 }

 #define L(x) ((x)*2-1)
 #define R(x) ((x)*2)

 int judge(int q)
 {
     int i,j,k,t,x,y,z,u,v;
     clr(C,0);
     for(i=N-1;i>=1;i--) for(j=M-1;j>=1;j--)
     {
         C[i][j]=B[i][j]-C[i+1][j]-C[i][j+1]-C[i+1][j+1];
     }
     clr(head,-1);
     e=0;
     FOR1(i,N-1) FOR1(j,M-1)
     {
         x=(M-j)%2?-1:1;
         y=(N-i)%2?-1:1;
         z=(N-i+M-j+1)%2?-1:1;
         FOR0(k,2) FOR0(t,2) if(!ok(C[i][j]+x*k+y*t+z*q))
         {
             u=k?L(i):R(i);
             v=!t?L(j+N-1):R(j+N-1);
             Add(u,v);

             u=t?L(j+N-1):R(j+N-1);
             v=!k?L(i):R(i);
             Add(u,v);
         }
     }
     n=N+M-2;
     if(!TWO_ST()) return 0;
     A[N][M]=q;
     FOR1(i,N-1) A[i][M]=(p[color[L(i)]]==1);
     FOR1(i,M-1) A[N][i]=(p[color[L(i+N-1)]]==1);
     for(i=N-1;i>=1;i--) for(j=M-1;j>=1;j--)
     {
         A[i][j]=B[i][j]-A[i+1][j]-A[i][j+1]-A[i+1][j+1];
     }
     FOR1(i,N)
     {
         FOR1(j,M) printf("%d",A[i][j]);
         puts("");
     }
     return 1;
 }


 int main()
 {
     scanf("%d%d",&N,&M);
     int i,j;
     for(i=1;i<N;i++) for(j=1;j<M;j++) scanf("%1d",&B[i][j]);
     if(judge(0)||judge(1)) return 0;
     puts("CORRUPT");
     return 0;
 }

  

你可能感兴趣的:(IP)