给你若干个与非门,全部输入是x的时候是一种情况。然后把其中一些输入改成常数,保留最少的x让输出情况和全部输入是x时一样。
因为x=0或1,所以输出一共只有四种情况:总为0,总为1,x和非x。所以,x最多只需要一个就行,如果为常数都不用x。因此二分查找x放在哪里就行。
注意的是这个输入 看得我很头疼……如果是负数,表示从第x个输入口输入数据,正数表示从第x个门输入数据。
AC代码:
#include <iostream>
#include <cstdio>
using namespace std;
struct gate
{
int a,b,o;
}gates[200010];
int v0,vn,ans,n,m;
int output(int k)
{
for(int i=1;i<=m;i++)
{
int ia=(gates[i].a<0)?(-gates[i].a>k):(gates[gates[i].a].o);
int ib=(gates[i].b<0)?(-gates[i].b>k):(gates[gates[i].b].o);
gates[i].o=!(ia&&ib);
}
return gates[m].o;
}
int solve()
{
int l=1,r=n;
while(l<r)
{
int m=(l+r)/2;
if(output(m)==vn)
r=m;
else
l=m+1;
}
return l;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1;i<=m;i++)
scanf("%d%d",&gates[i].a,&gates[i].b);
v0=output(0);
vn=output(n);
if(v0==vn)
{
for(int i=0;i<n;i++)
putchar('0');
printf("\n");
}
else
{
ans=solve();
for(int i=1;i<ans;i++)
putchar('0');
putchar('x');
for(int i=ans+1;i<=n;i++)
putchar('1');
cout<<endl;
}
}
return 0;
}