这个题其实就是sat问题,是个NPC,所以做这题基本上是休闲。
但其实分析数据可以发现每个数据都是有目的,并不完全是混乱的boolean表达式。
首先对于第一、二两个点数据其实质就是枚举,让我想到了NOIP04年的等价表达式。。。囧。。。
point 3、4、5、6就是2-sat问题,本弱菜写2-sat的题目不多,基本上中规中矩除读入140几行。构图什么的几乎木有,裸的2-sat问题,345都可以满足,6号点有三个无法满足,不知是哪几个,所以就为了方便删了最后三个,好像碰上了的说。。。
如果不会2-sat自行百度“赵爽 2-sat”,写得很详细。由于这东西并不是热点,考不考是个未知。
7号点是状态压缩么,将m个表达式按照读入的第一个变元序号排序,f[i][s]表示以i个式子变元为首的连续11个变元赋值为s的状态下前i个式子最多满足多少个,
然后就是环的处理,以跨过n号变元的式子为头,再做一遍DP,与之前的取最优值就可以了。
8号点二分图匹配,看一下数据就知道,对于每个式子,将差值为1的点捆绑为一点,以变元可满足式子的赋值作为压缩的状态赋为边的属性,匈牙利的时候记录选的边是哪条
9号点完全就是sat问题了,除了随机模拟退火外没有好的算法。
10号点是个构造,很容易的,但是DP解法就不知如何想了。
Code:point 3、4、5、6
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
typedef int arr2[6000005];
typedef int arr[400005];
arr2 foll,link,poin,next,sta;
arr head,last,tops,anti,vis,low,rea,f,degree,bro,son,color,que;
int n=0,m=0,e=1,time=0,top=0,tail=0,hea=0;
bool view[400005];
inline int min(int q,int p)
{
return q<p?q:p;
}
void add(int u,int v)
{
next[++e]=head[u];
head[u]=e;
link[e]=v;
if (next[e]==0) last[u]=e;
}
void addoth(int u,int v)
{
foll[++e]=tops[u];
tops[u]=e;
poin[e]=v;
}
void init34()
{
char ch=0;
int i=0,u=0,v=0;
for (i=1;i<=m;i++)
{
scanf("%c",&ch);
if (ch=='~')
{
scanf("x%d",&u);
u=anti[u];
scanf("|%c",&ch);
if (ch=='~')
{
scanf("x%d\n",&v);
v=anti[v];
}
else
scanf("%d\n",&v);
}
else
{
scanf("%d|",&u);
scanf("%c",&ch);
if (ch=='~')
{
scanf("x%d\n",&v);
v=anti[v];
}
else
scanf("%d\n",&v);
}
add(anti[v],u);
add(anti[u],v);
}
}
void init5()
{
int i=0,j=0,u=0;
char ch=0;
if (m==33333) m-=3;
for (i=1;i<=m;i++)
{
hea=0;
scanf("%c",&ch);
for (scanf("%c",&ch);ch!=')';scanf("%c",&ch))
{
if (ch=='&') scanf("%c",&ch);
if (ch=='~')
{
scanf("x%d",&u);
u=anti[u];
}
else
scanf("%d",&u);
que[++hea]=u;
}
scanf("|%c",&ch);
for (scanf("%c",&ch);ch!=')';scanf("%c",&ch))
{
if (ch=='&') scanf("%c",&ch);
if (ch=='~')
{
scanf("x%d",&u);
u=anti[u];
}
else
scanf("%d",&u);
for (j=1;j<=hea;j++)
{
add(anti[que[j]],u);
add(anti[u],que[j]);
}
}
scanf("%c",&ch);
}
}
void dfs(int s)
{
vis[s]=1;
rea[s]=low[s]=++time;
sta[++top]=s;
int ne=0,y=0;
for (ne=head[s];ne;ne=next[ne])
{
y=link[ne];
if (vis[y]==0) dfs(y);
if (vis[y]==1) low[s]=min(low[s],low[y]);
}
if (rea[s]==low[s])
{
for(;sta[top+1]!=s;top--)
{
y=sta[top];
f[y]=s;
vis[y]=2;
if (y==s) break;
bro[y]=son[s];
son[s]=y;
}
top--;
}
}
void edgeanti(int s)
{
int ne=0,y=0;
view[s]=1;
++time;
for (ne=head[s],y=f[link[ne]];ne;ne=next[ne],y=f[link[ne]])
if (vis[y]!=time && y!=s)
{
vis[y]=time;
addoth(y,s);
++degree[s];
}
}
void bfs(int s)
{
color[s]=3;
int ne=0,y=0;
for (ne=tops[s],y=poin[ne];ne;ne=foll[ne],y=poin[ne])
if (!color[y]) bfs(y);
}
void topsort()
{
int i=0;
top=0,tail=0;
for (i=1;i<=2*n;i++)
if (view[f[i]])
{
view[f[i]]=0;
if (degree[f[i]]==0)
sta[++tail]=f[i];
}
int ne=0,y=0,x=0;
while (top<tail)
{
x=sta[++top];
for (ne=tops[x],y=poin[ne];ne;ne=foll[ne],y=poin[ne])
{
degree[y]--;
if (degree[y]==0)
sta[++tail]=y;
}
}
for (i=1;i<=tail;i++)
if (!color[x = sta[i]])
{
color[x]=2;
if (!color[y = f[anti[x]]]) bfs(y);
for (ne=son[x],y=f[anti[ne]];ne;ne=bro[ne],y=f[anti[ne]])
{
if (!color[y]) bfs(y);
}
}
}
int main(int argc,char* argv[])
{
char inname[200],outname[200];
memset(inname,0,sizeof(inname));
memset(outname,0,sizeof(outname));
int i=0;
sprintf(inname,"opt%s.in",argv[1]);
sprintf(outname,"opt%s.out",argv[1]);
freopen(inname,"r",stdin);
freopen(outname,"w",stdout);
scanf("%d%d\n",&n,&m);
for (i=1;i<=n;i++)
{
anti[i]=i+n;
anti[i+n]=i;
}
if (inname[3]=='3'||inname[3]=='4')
init34();
else
init5();
for (i=1;i<=2*n;i++)
if (!vis[i])
dfs(i);
memset(vis,0,sizeof(vis));
int ne=0;
for (i=1;i<=2*n;i++)
if (!vis[f[i]])
{
vis[f[i]]=1;
ne=son[f[i]];
while (ne)
{
next[last[ne]]=head[f[i]];
head[f[i]]=head[ne];
head[ne]=0;
ne=bro[ne];
}
}
memset(vis,0,sizeof(vis));
time=0;
e=0;
for (i=1;i<=2*n;i++)
if (!view[f[i]])
edgeanti(f[i]);
topsort();
for (i=1;i<=n;i++)
if (color[f[i]]==2)
printf("1\n");
else
printf("0\n");
return 0;
}
Code point 7:
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
struct fomula
{
int sta,appear,posine;
bool spe;
} fomu[505];
int n=0,m=0;
int f[505][2052],path[505][2052];
int code[105];
bool flag[505][2052];
int cmp(const void *p,const void *q)
{
return (*(fomula*)p).sta-(*(fomula*)q).sta;
}
void init()
{
int i=0,u=0,delta=0;
char ch=0;
for (i=1;i<=m;i++)
{
scanf("%c",&ch);
if (ch=='~')
{
scanf("x%d",&u);
fomu[i].appear=1;
fomu[i].posine=0;
}
else
{
scanf("%d",&u);
fomu[i].appear=1;
fomu[i].posine=1;
}
fomu[i].sta=u;
for (scanf("%c",&ch);ch!='\n';scanf("%c",&ch))
{
if (ch=='&') scanf("%c",&ch);
if (ch=='~')
{
scanf("x%d",&u);
delta=u-fomu[i].sta;
if (delta<0)
{
delta+=100;
fomu[i].spe=1;
}
fomu[i].appear+=(1<<delta);
}
else
{
scanf("%d",&u);
delta=u-fomu[i].sta;
if (delta<0)
{
delta+=100;
fomu[i].spe=1;
}
fomu[i].appear+=(1<<delta);
fomu[i].posine+=(1<<delta);
}
}
}
}
bool infer(fomula a,int state)
{
int i=0;
for (i=0;i<=10;i++)
{
if (a.appear&1)
if (a.posine&1)
{
if (!(state&1)) return 0;
}
else
{
if (state&1) return 0;
}
a.appear>>=1;
a.posine>>=1;
state>>=1;
}
return 1;
}
void dfs(int s,int state)
{
int i=0,stmp=state;
if (s==0) return;
for (i=0;i<=10;i++)
{
code[i+fomu[s].sta]=stmp&1;
stmp>>=1;
}
if (flag[s][state])
dfs(s-1,path[s][state]);
}
bool infer(fomula a)
{
int i=0;
for (i=0;i<=10;i++)
{
if (a.appear&1)
if (a.posine&1)
{
if (!code[i+a.sta]) return 0;
}
else
{
if (code[i+a.sta]) return 0;
}
}
return 1;
}
int main()
{
freopen("opt7.in","r",stdin);
freopen("opt7.out","w",stdout);
scanf("%d%d\n",&n,&m);
init();
qsort(fomu+1,m,sizeof(fomu[0]),cmp);
fomu[0].sta=1;
fomu[0].appear=(1<<11)-1;
fomu[0].posine=(1<<11)-1;
int state=0,i=0,now=0,nex=0,tmp=0,nstate=0,fixed=0,delta=0,rest=0;
for (i=0;i<m && (!fomu[i].spe);i++)
for (state=0;state<=(1<<11)-1;state++)
{
now=fomu[i].sta;
nex=fomu[i+1].sta;
delta=nex-now;
fixed=state>>delta;
if (!fomu[i].spe)
for (rest=0;rest<=(1<<delta)-1;rest++)
{
nstate=fixed+(rest<<(11-delta));
if (infer(fomu[i+1],nstate)) tmp=f[i][state]+1;
else tmp=f[i][state];
if (tmp>=f[i+1][nstate])
{
path[i+1][nstate]=state;
f[i+1][nstate]=tmp;
flag[i+1][nstate]=1;
}
}
else
break;
}
int tend=i-1,stmp=0,anss=0,anst=0;
delta=n-(fomu[tend].sta+10);
if (delta<0) delta=0;
for (nstate=0;nstate<=1<<delta;nstate++)
{
for (state=0;state<=(1<<11)-1;state++)
{
memset(code,0,sizeof(code));
for (stmp=nstate,i=fomu[tend].sta+11;i<=n;i++,stmp>>=1)
code[i]=stmp&1;
dfs(tend,state);
for (i=tend+1;i<=m;i++)
if (infer(fomu[i]))
f[tend][state]++;
if (f[tend][state]>=f[tend][anss])
{
anss=state;
anst=nstate;
}
}
}
memset(code,0,sizeof(code));
for (stmp=anst,i=fomu[tend].sta+11;i<=n;i++,stmp>>=1)
code[i]=stmp&1;
dfs(tend,anss);
for (i=1;i<=n;i++)
printf("%d\n",code[i]);
return 0;
}
Code point 8:
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
int e=1,n=0,m=0,nodesnum=0,top=0,tail=0,hea=0,bot=0;
int point[10005],li[10005],f[10005],attr[20005],head[10005],next[20005],link[20005],mych[10005],sta[10005],que[10005];
bool vis[10005];
void add(int u,int v,int e)
{
next[e]=head[u];
head[u]=e;
link[e]=v;
}
void init()
{
int i=0,u=0,last=0,thead=0,lastlast=0;
char ch=0;
for (i=1;i<=m;i++)
{
last=-10;
for (scanf("%c",&ch);ch!='\n';scanf("%c",&ch))
{
if (ch=='&') scanf("%c",&ch);
if (ch=='~')
{
scanf("x%d",&u);
if (u-last>1)
{
lastlast=thead;
thead=u;
if (point[thead]==0) point[thead]=++nodesnum;
++e;
}
}
else
{
scanf("%d",&u);
if (u-last>1)
{
lastlast=thead;
thead=u;
if (point[thead]==0) point[thead]=++nodesnum;
++e;
}
attr[e]+=(1<<(u-thead));
}
f[u]=thead;
last=u;
}
add(point[lastlast],point[thead],e-1);
add(point[thead],point[lastlast],e);
}
}
bool find(int x)
{
if (x==0) return 0;
vis[x]=1;
for (int ne=head[x],y=link[ne];ne;ne=next[ne],y=link[ne])
{
if (!vis[y])
{
vis[y]=1;
if (li[y]==0 || find(li[y]))
{
li[y]=x;
mych[y]=ne^1;
mych[x]=ne;
return 1;
}
}
}
return 0;
}
bool infer(int s)
{
int nst=attr[mych[point[f[s]]]];
int delta=s-f[s];
return (nst>>delta)&1;
}
void bfs(int s)
{
vis[s]=1;
sta[++tail]=s;
int ne=0,x=0,y=0;
while (top<tail)
{
while (top<tail)
{
x=sta[++top];
for (ne=head[x],y=link[ne];ne;ne=next[ne],y=link[ne])
if (!vis[y])
{
vis[y]=1;
que[++bot]=y;
}
}
while (hea<bot)
{
x=que[++hea];
for (ne=head[x],y=link[ne];ne;ne=next[ne],y=link[ne])
if (!vis[y])
{
vis[y]=1;
sta[++tail]=y;
}
}
}
}
int main()
{
freopen("opt8.in","r",stdin);
freopen("opt8.out","w",stdout);
scanf("%d%d\n",&n,&m);
init();
int i=0,delta=0,x=0,j=0;
for (i=1;i<=nodesnum;i++)
if (!vis[i])
bfs(i);
for (i=1;i<=tail;i++)
{
memset(vis,0,sizeof(vis));
find(sta[i]);
}
for (i=1;i<=n;i++)
if (infer(i))
printf("1\n");
else
printf("0\n");
return 0;
}