http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4106
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 xconsists of only 0 and 1. Array c consists of only 0, 1 and 2. The lengths of array a, b and c are m while 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
题目大意:
给定a,b,c,x四个数组。x只包含{0,1},c只包含{0,1,2,},a和b里面的元素都是从0-n-1的数,现要求这段代码中的dep的最大数 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[i]和b[i]值x[]都有一定的取值{0,1},当然x[a[i]]如果等于0就不能再等于其他的数,如果等于1了,也是同理。这就转化成了典型的2-sat问题,注意建边的规则,详见代码。
ps:我是改了,模板想用还得自己写,用别人的就是不靠谱。
#include <cstdio> #include <iostream> #include <string.h> #include <cmath> #include <stack> using namespace std; //============================================================= //2-sat模板 const int maxn=505; const int maxm=100005; int n,m,a[maxm][3]; struct note { int to; int next; }edge[maxn*2*maxn]; int head[maxn]; int ip; int dfn[maxn],low[maxn],sccno[maxn],cnt,scc,instack[maxn]; stack<int>stk; void addedge(int u,int v) { edge[ip].to=v,edge[ip].next=head[u],head[u]=ip++; } // x = xval or y = yval void add_cluse(int x,int xval,int y,int yval) { x=x*2+xval; y=y*2+yval; addedge(x,y^1); addedge(y,x^1); } void dfs(int u) { dfn[u]=low[u]=++scc; stk.push(u); instack[u]=1; for (int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].to; if (!dfn[v]) { dfs(v); low[u]=min(low[u],low[v]); } else if (instack[v]) low[u]=min(low[u],dfn[v]); } if (low[u]==dfn[u]) { cnt++; int x; do { x=stk.top(); stk.pop(); sccno[x]=cnt; instack[x]=0; }while (x!=u); } } bool solve() { scc=cnt=0; memset(sccno,0,sizeof(sccno)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(instack,0,sizeof(instack)); while (!stk.empty()) stk.pop(); for (int i=0; i<2*n; i++) if (!dfn[i]) dfs(i); for (int i=0; i<2*n; i+=2) { if (sccno[i]==sccno[i^1]) return false; } return true; } //solve返回true证明2-sat有解,否则没解 //============================================================ void build(int mid) { memset(head,-1,sizeof(head)); ip=0; for(int i=0; i<mid; i++) { if(a[i][2]==0) add_cluse(a[i][0],0,a[i][1],0); if(a[i][2]==1) { add_cluse(a[i][0],1,a[i][1],0); add_cluse(a[i][0],0,a[i][1],1); } if(a[i][2]==2) add_cluse(a[i][0],1,a[i][1],1); } } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=0; i<m; i++) scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]); int l=0,r=m,num; while(l<=r) { int mid=(l+r)>>1; build(mid); if(solve()) { num=mid; //printf("(%d)\n",num); l=mid+1; } else r=mid-1; } printf("%d\n",num); } return 0; }