uva1607 - Gates

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4482

题意:给出一个与非门电路,在所有输入都为x的情况下,该电路会输出一个结果,让你将一些输入固定为常数,让x最少的情况下完成相同功能。

分析:输入只有一个值,那么整个电路只可能有四种功能·,常数0,常数1,x,非x。首先如果我们输入0和1得到相同的结果,说明电路为常数电路,任意输出即可(全0,全1)。如果输出不一样,说明电路功能为x或非x,一定有一种情况在只有1个x就完成该功能。


给出证明,我们已知输入全0,即111……1(始态)时输出和000……0(终态)时不同,那么11111……1,01111……1,00111……1,00011……1,-------,00000……0渐变过程一定存在这种情况…1…--->…0…的过程中输出由始态转变为终态,即为所求解(因为该过程可逆,…0…--->…1…输出同样改变)。


解法就是这样了,但还有一点要注意,m太大了,耗时可能很多,用二分枚举位置可以求出其中一个可行解,时间消耗也不大。

代码:

#include<iostream>
#include<cmath>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define MOD 100000007
#define INF 0x3f3f3f3f
using namespace std;

const int maxm=200000+5;
int n,m;

struct node
{
    int a,b,w;
}q[maxm];

int print(int k)
{
    for(int i=1;i<=m;i++)
    {
        int x=q[i].a;
        int y=q[i].b;
        int va=x<0?-x>k:q[x].w;
        int vb=y<0?-y>k:q[y].w;
        q[i].w=!(va&&vb);
    }
    return q[m].w;
}
int solve(int vn)
{
    int l=1,r=n;
    while(l<r)
    {
        int mid=l+(r-l)/2;
        if(print(mid)==vn)r=mid;
        else l=mid+1;
    }
    return l;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
            scanf("%d%d",&q[i].a,&q[i].b);
        int v0=print(0);
        int vn=print(n);
        if(v0==vn)
        {
            for(int i=1;i<=n;i++)printf("0");
        }
        else
        {
            int x=solve(vn);
            for(int i=1;i<x;i++)printf("0");
            printf("x");
            for(int i=x+1;i<=n;i++)printf("1");
        }
        printf("\n");
    }
    return 0;
}


你可能感兴趣的:(uva1607 - Gates)