题意:给出a[i], b[i], c[i],构造x[i],求出满足1<=x<=L, c[i] != x[a[i]] + x[b[i]]的最大L,a,b,x是01数组,c使0~2的数组
题解:若加入关系i使得x无法构造,则i+1也无法加入,满足二分性质。对于a[i], b[i], c[i], 可以求出x[a[i]], x[b[i]]不可取的取值,用2-sat维护x[i]的取值判断冲突。
2-sat见
http://blog.csdn.net/cevaac/article/details/39719813
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int N = 10010;
const int M = 1000000;
using namespace std;
#define bf(x) ((x)<<1)
#define bt(x) ((x)<<1|1)
int ind[N], id[N];
int t[M], nt[M];
int dfn[N], low[N];
int s[N];
bool vis[N];
int l;
int n;
int cnt, num, idn;
int a[N], b[N], c[N];
void add(int i, int j)
{
cnt++;
t[cnt] = j;
nt[cnt] = ind[i];
ind[i] = cnt;
}
void tarjan(int x)
{
num++;
dfn[x] = low[x] = num;
s[++l] = x;
vis[x] = true;
for(int k = ind[x]; k != -1; k = nt[k])
{
if(dfn[t[k]] == 0) tarjan(t[k]);
if(vis[t[k]]) low[x] = min(low[x], low[t[k]]);
}
if(dfn[x] == low[x])
{
idn++;
while(true)
{
int tmp = s[l--];
id[tmp] = idn;
vis[tmp] = false;
if(tmp == x) break;
}
}
}
bool chk(int M)
{
for(int i = 0; i < 2 * n; i++) ind[i] = -1;
cnt = 0;
for (int i = 0; i < M; i++)
{
if (c[i] == 0)
{
add(bf(a[i]),bt(b[i]));
add(bf(b[i]),bt(a[i]));
}
else if (c[i] == 1)
{
add(bf(a[i]), bf(b[i]));
add(bf(b[i]), bf(a[i]));
add(bt(a[i]), bt(b[i]));
add(bt(b[i]), bt(a[i]));
}
else
{
add(bt(a[i]),bf(b[i]));
add(bt(b[i]),bf(a[i]));
}
}
//cout << cnt << endl;
memset(vis, 0, sizeof vis);
num = 0;
idn = 0;
l = 0;
memset(dfn, 0, sizeof dfn);
memset(low, 0, sizeof low);
memset(id, 0, sizeof id);
for(int i = 0; i < 2 * n; i++)
{
if(dfn[i] == 0) tarjan(i);
}
for(int i = 0; i < 2 * n; i++)
{
if(id[i] == id[i ^ 1]) return false;
}
return true;
}
int main()
{
//freopen("test.in", "r", stdin);
int t;
scanf("%d",&t);
while (t--)
{
int m;
scanf("%d%d",&n,&m);
for(int i = 0; i < m; i++) scanf("%d%d%d", &a[i], &b[i], &c[i]);
int l = 0, r = m;
while(l < r - 1)
{
int mid = (l + r) / 2;
if(chk(mid)) l = mid;
else r = mid;
}
if(chk(r)) printf("%d\n", r);
else printf("%d\n", l);
}
return 0;
}