HDU 3715 Go Deeper 二分 + 2-sat

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

題目:

http://acm.hdu.edu.cn/showproblem.php?pid=3715

題意:

給定一段遞迴虛擬碼,問執行這段虛擬碼遞迴的最深層數

思路:

二分枚舉答案用2-sat判定是否可行。具體建圖如下:如果c[i] == 0,那麼a[i] OR b[i],如果c[i] == 1,那麼(a[i] AND b[i]) OR (~a[i] AND ~b[i]),如果c[i] == 2,那麼NOT(a[i] AND b[i]),然後強連通縮點判斷i和~i是否在同一個環內

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <cmath>using namespace std;const int N = 410;const double eps = 1e-8;struct edge{    int to, next;} g[N*N*2];int cnt, head[N], cnt1, head1[N];int dfn[N], low[N], scc[N], st[N], top, num, idx;int a[N*N], b[N*N], c[N*N];bool vis[N];int n, m;void add_edge(int v, int u){    g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++;}void init(){    memset(head, -1, sizeof head);    memset(dfn, -1, sizeof dfn);    memset(vis, 0, sizeof vis);    top = num = idx = cnt = 0;}void tarjan(int v){    dfn[v] = low[v] = ++idx;    vis[v] = true, st[top++] = v;    int u;    for(int i = head[v]; i != -1; i = g[i].next)    {        u = g[i].to;        if(dfn[u] == -1)        {            tarjan(u);            low[v] = min(low[v], low[u]);        }        else if(vis[u]) low[v] = min(low[v], dfn[u]);    }    if(dfn[v] == low[v])    {        num++;        do        {            u = st[--top];            vis[u] = false;            scc[u] = num;        }        while(u != v);    }}bool work(int mid){    init();    for(int i = 0; i < mid; i++)    {        if(c[i] == 0)        {            add_edge(a[i] + n, b[i]), add_edge(b[i] + n, a[i]);        }        else if(c[i] == 1)        {            add_edge(a[i], b[i]), add_edge(b[i], a[i]);            add_edge(a[i] + n, b[i] + n), add_edge(b[i] + n, a[i] + n);        }        else if(c[i] == 2)        {            add_edge(a[i], b[i] + n), add_edge(b[i], a[i] + n);        }    }    for(int i = 0; i < 2*n; i++)        if(dfn[i] == -1) tarjan(i);    for(int i = 0; i < n; i++)        if(scc[i] == scc[i+n]) return false;    return true;}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], &b[i], &c[i]);        int l = 0, r = m, res;        while(l <= r)        {            int mid = (l + r) / 2;            if(work(mid)) l = mid + 1, res = mid;            else r = mid - 1;        }        printf("%d\n", res);    }    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.