HDOJ 3715 Go Deeper (2Sat: 二分答案判定)

//HDOJ 3715 Go Deeper (2Sat: 二分答案判定)

/*
题意:给定一个程序 ,求go(0, n, m)输出的值中的最大值
	  程序如下:
		go(int dep, int n, int m)
		begin
		output the value of dep.
		if dep < m and x[a[dep]] + x[b[dep]] != c[dep] then go(dep + 1, n, m)
		end
	  a[],b[]由0、1、2...n构成,长度为m
	  c[]数组由0、1、2构成,长度为m
	  x[]数组由0、1构成,长度为n

思路:输出的数值大小由x[]数组的赋值情况而定,二分dep做2Sat即可

构图:	  
x取0:i,j
x取1:i',j'

1. 若c==0 则i->j' j->i'
2. 若c==1 则i'->j' j'->i' i->j j->i
3. 若c==2 则i'>j j'->i
*/

#include<stdio.h>
#include<iostream>
#include<queue>
#include<string>
using namespace std;

#define N 410
#define M 50000
#define NN 10005

int stack[N], LOW[N], DFN[N], belong[N],head[N];
int top, cnt, tot, Index, num;
bool inStack[N];

int n,m;
int a[NN],b[NN],c[NN],x[N];

struct Edge{
    int to;
    int next;
}edge[M];

void addedge(int from, int to){
    edge[num].to = to;
    edge[num].next = head[from];
    head[from] = num++;
}

void Tarjan(int u) { 
    int v;
    stack[++top] = u;
    inStack[u] = true;
    LOW[u] = DFN[u] = ++Index;
	
    for(int i = head[u]; i != -1; i = edge[i].next){
        v = edge[i].to;
        if (!DFN[v]) {
            Tarjan(v);
            if (LOW[u] > LOW[v])
                LOW[u] = LOW[v];
        }     
        else if (inStack[v] && LOW[u] > DFN[v])
            LOW[u] = DFN[v];
    }
    if (LOW[u] == DFN[u]) {    
        cnt++;    
        do {
            v = stack[top--];
            inStack[v] = false;
            belong[v] = cnt;
        } while (v != u);
    }
}

void init(){
    memset(head,-1,sizeof(head));
    memset(DFN,0,sizeof(DFN));
    memset(inStack,0,sizeof(inStack));
    cnt = Index = top = num  = 0;
}

void build(int mid){
    int i,x,y;
    init();
    for(i = 0; i < mid; i++){
        x = a[i];
        y = b[i];
        if(c[i] == 0){
            addedge(x,y+n);
            addedge(y,x+n);
        }
        else if(c[i] == 1){
            addedge(x,y);
            addedge(y,x);
            addedge(x+n,y+n);
            addedge(y+n,x+n);
        }
        else if(c[i] == 2){
            addedge(x+n,y);
            addedge(y+n,x);
        }
    }
}

int main(){
    int T,i;
    int left,right,mid,max;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&m);
        for(i = 0; i < m; i++)
            scanf("%d %d %d",&a[i],&b[i],&c[i]);
        
        left = 0;
        right = m;
        max = 0;
		
        while(right >= left){
            mid = (right + left) >> 2;
            build(mid);
            
            for(i = 0; i < 2 * n; i++
                if (!DFN[i])
                    Tarjan(i);
                
			for(i = 0; i < n; i++)
				if(belong[i] == belong[i+n])
					break;
					
			if(i < n)
				right = mid - 1;
			else{
				max = mid;
				left = mid + 1;
			}
        }
        printf("%d\n",max);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值