這種題目。。。哎。。智商不夠用啊。。由於輸入只有一個x的值,所以電路無論多複雜,最終結果只有1,0,x或!x(所以可以這樣理解,當電路的輸出與x相關時,原電路一定可以等效爲輸入序列只有一個x其餘均爲0/1的情況)。取x爲0與x爲1,如果電路的輸出結果相同,那麼電路的輸出結果一定是常數,那麼隨便輸出一串0,1就行。。否則,由前面的討論我們只需要找到那個填上x的位置,從全爲0的輸入開始,對於全爲0的輸入記其輸出爲a。每次將輸入序列的第一個0替換爲1。直到找到一個k使得輸入序列的前k個數均爲1時,該序列的輸出結果不是a爲止,那麼我們的輸入序列可以簡化爲111...1(k-1個1)x00000...(後面全是0)。因爲對於全爲1的輸入序列,其輸出不等於a所以符合條件的k一定存在,即這樣的算法一定會給出答案。關於k的找法用二分,詳見代碼。
AC代碼如下:(參考了編程。。畢竟我真的不會寫這題。。)
#include <cstdio>
using namespace std;
int n,m,inp1[200005],inp2[200005],out[2000005];
int calculate(int k) //當輸入序列的前k個數均爲1時求電路的輸出
{
for(int i=1;i<=m;i++)
{
int a,b;
if(inp1[i]<0)
a=(-inp1[i]<=k);
else
a=out[inp1[i]];
if(inp2[i]<0)
b=(-inp2[i]<=k);
else
b=out[inp2[i]];
out[i]=!(a&b);
}
return out[m];
}
int main(int argc, char const *argv[])
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d %d", &n, &m);
for(int i=1;i<=m;i++)
scanf("%d %d", &inp1[i],&inp2[i]);
int x,y;
x=calculate(0);
y=calculate(n);
if(x==y)
{
for(int i=1;i<=n;i++)
printf("0");
printf("\n");
}
else
{
int L=0,R=n,mid=1; //二分查找
while(R-L>1)
{
mid=(L+R)/2;
if(calculate(mid)==x)
L=mid;
else
R=mid;
}
for(int i=1;i<=n;i++)
{
if(i<R) printf("1");
else if(i==R) printf("x");
else printf("0");
}
printf("\n");
}
}
return 0;
}