题意:给你一个递推式,问你最多能循环几层?
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
递推式如上,若想循环下去,就要使第四行式子中“ x[a[dep]] + x[b[dep]] != c[dep]”成立,满足下面条件:
当c[i] == 0,有a[i] + n -> b[i] && b[i] + n -> a[i];
当c[i] == 1,有a[i] + n -> b[i] + n && b[i] + n -> a[i] + n && a[i] -> b[i] && b[i] -> a[i];
当c[i] == 2,有a[i] -> b[i] + n && b[i] -> a[i] + n;
连完边后跑2-SAT,答案问最大的,所以二分去求即可。
链接:hdu - 3715
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 10005;
const int maxm = 500005;
struct node {
int s, t;
int nxt;
} e[maxm];
int n, m;
int idx, ans, tp, cont;
int dfn[maxn], vis[maxn], low[maxn], head[maxn], st[maxn], belong[maxn];
void init() {
cont = 0;
memset(head, -1, sizeof(head));
memset(vis, 0, sizeof(vis));
memset(dfn, 0, sizeof(dfn));
idx = tp = ans = 0;
}
void add(int s, int t) {
e[cont].s = s;
e[cont].t = t;
e[cont].nxt = head[s];
head[s] = cont++;
}
void tarjan(int u) {
dfn[u] = low[u] = ++idx;
vis[u] = 1;
st[++tp] = u;
int v ;
for(int i = head[u]; i != -1; i = e[i].nxt) {
v = e[i].t ;
if(!dfn[v]) {
tarjan(v) ;
low[u] = min(low[u],low[v]);
}
else if(vis[v])
low[u] = min(low[u],dfn[v]);
}
if(dfn[u] == low[u]) {
ans++;
while(1) {
v = st[tp--];
vis[v] = 0;
belong[v] = ans;
if(v == u)
break;
}
}
}
bool _2sat() {
for(int i = 0; i < 2 * n; i++)
if(!dfn[i])
tarjan(i) ;
for(int i = 0; i < n; i++)
if(belong[2 * i] == belong[(2 * i) ^ 1])//矛盾
return false;
return true;
}
int a[maxn], b[maxn], c[maxn];
int main()
{
int t;
cin >> t;
while(t--) {
scanf("%d %d", &n, &m);
for(int i = 0; i < m; i++) {
scanf("%d %d %d", &a[i], &b[i], &c[i]);
}
int ans = 0;
int l = 0, r = m;
while(l <= r) {
int mid = (l + r) / 2;
init();
for(int i = 0; i < mid; i++) {
if (c[i] == 0) {
add(a[i] + n, b[i]);
add(b[i] + n, a[i]);
}
else if (c[i] == 1) {
add(a[i], b[i]);
add(b[i], a[i]);
add(a[i] + n, b[i] + n);
add(b[i] + n, a[i] + n);
}
else {
add(a[i], b[i] + n);
add(b[i], a[i] + n);
}
}
int flag = 1;
for(int i = 0; i < n * 2; i++) {
if(!dfn[i]) tarjan(i);
}
for(int i = 0; i < n; i++) {
if(belong[i] == belong[i + n]) {
flag = 0;
break;
}
}
if(flag) {
l = mid + 1;
}
else {
r = mid - 1;
}
}
cout << r << endl;
}
return 0 ;
}