UVALive 5010 2-sat+二分

来源:互联网 发布:i o接线端口 编辑:程序博客网 时间:2024/06/10 11:24

链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3011

题意:给出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;}


0 0
原创粉丝点击