您的位置:首页 > 编程语言 > Go语言

Go Deeper(2010成都现场赛题)(2-sat)

2014-07-25 00:53 375 查看
G - Go Deeper
Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu

Description

Here is a procedure's pseudocode:

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


In this code n is an integer. a, b, c and x are 4 arrays of integers. The index of array always starts from 0. Array a and b consist of non-negative integers smaller than n. Array x consists of only 0 and 1. Array c consists of only 0, 1 and 2. The lengths of array a, b and c are mwhile the length of array x is n.

Given the elements of array a, b, and c, when we call the procedure go(0, n , m) what is the maximal possible value does the procedure output?

Input

There are multiple test cases. The first line of input is an integer T (0 < T ≤ 100), indicating the number of test cases. Then T test cases follow. Each case starts with a line of 2 integers n and m (0 < n ≤ 200, 0 < m ≤ 10000). Then m lines of 3 integers follow. The i-th(1 ≤ i ≤m) line of them are ai-1 ,bi-1 and ci-1 (0 ≤ ai-1, bi-1 < n, 0 ≤ ci-1 ≤ 2).

Output

For each test case, output the result in a single line.

Sample Input

3
2 1
0 1 0
2 1
0 0 0
2 2
0 1 0
1 1 2


Sample Output

1
1
2

题目大意:
 
给定一些方程,x[]数组未知,求前面最多能够有多少方程x[a]+x!=c能够被满足。
 其中 c=0,1,2
  x[]={0,1}
相当于裸的2sat问题,加上二分
  
  强烈建议阅读 kuangbin大神对2-sat的总结:http://www.cnblogs.com/kuangbin/archive/2012/10/05/2712429.html

总的来说,就是当 a or b 时 连接 a' -> b 与 b' -> a 的边,然后进行强连通判断是否出现 a 与 a' ...在同一个连通分量中,若在则不可能。

建立数a的两个状态,即a与a',相当于x[a]=1 和 x[a']=0

x[a]+x[b]!=0   [b]=>   a or b   =>   a'->b 且 a->b'
x[a]+x[b]!=1   =>   (a and b) or (a' and b') == a or b' 且 a' or b   =>   a'->b' 且 b->a 且 a->b 且 b'->a
x[a]+x[b]!=2   =>   a' or b'   =>   a->b' 且 a'->b

按上面来建图判断即可


#include<cstdio>
#include<cstring>
int e[50000],pd[50000],be[800],ne[50000],all;
int dfn[800],low[800],instack[800],belong[800],stack[800],stak,curr,num;
int a,b,c,n,m,l,r,mid,flag;
void add(int x,int y,int p){
e[++all]=y;
pd[all]=p;
ne[all]=be[x];
be[x]=all;
}
void tarjan(int x){
instack[x]=1;
stack[++stak]=x;
dfn[x]=low[x]=++curr;
for(int j=be[x];j!=0;j=ne[j])
if(pd[j]<=mid){
if(!dfn[e[j]]){
tarjan(e[j]);
if(low[x]>low[e[j]]) low[x]=low[e[j]];
}else if(instack[e[j]]&&low[x]>low[e[j]])
low[x]=low[e[j]];
}
if(dfn[x]==low[x]){
int j;
++num;
do{
j=stack[stak--];
instack[j]=0;
belong[j]=num;
}while(j!=x);
}
}
int solve(){
curr=stak=num=0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(instack,0,sizeof(instack));
for(int i=0;i<2*n;i++)
if(!dfn[i]) tarjan(i);
flag=0;
for(int i=0;i<n;i++)
if(belong[2*i]==belong[2*i+1]){
flag=1;
break;
}
return flag;
}
int main()
{
int tt;
scanf("%d",&tt);
while(tt--){
scanf("%d%d",&n,&m);
all=0;
memset(e,0,sizeof(e));
memset(be,0,sizeof(be));
memset(ne,0,sizeof(ne));
memset(pd,0,sizeof(pd));
for(int i=0;i<m;i++){
scanf("%d%d%d",&a,&b,&c);
switch (c){
case 0: add(2*a+1,2*b,i);
add(2*b+1,2*a,i);
break;
case 1: add(2*a,2*b,i);
add(2*b+1,2*a+1,i);
add(2*b,2*a,i);
add(2*a+1,2*b+1,i);
break;
case 2: add(2*a,2*b+1,i);
add(2*b,2*a+1,i);
break;
}
}
l=0;r=m-1;
while(l<r-1){
mid=(l+r)/2;
if(solve()) r=mid; else l=mid;
}
mid=r;
if(!solve()) printf("%d\n",r+1);
else printf("%d\n",l+1);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: