zoukankan      html  css  js  c++  java
  • hdu3715

    hdu3715

    题意

    给出一个递归的伪代码,当 x[a[dep]] + x[b[dep]] != c[dep],就向下递归,给出a,b,c数组的值 问 dep 最大多少。其中 0 <= c[i] <= 2 ,0 <= x[i] <= 1。

    分析

    x 取值存在对立关系( 1或0 ),那么可以通过不等式进行建边,有三种情况,

    1. 当 c[i] = 2 时,有 A and B = 0,即不能全部为真
    2. 当 c[i] = 1 时,有 A xor B = 0,加起来不能等于1
    3. 当 c[i] = 0 时,有 A or B != 0

    二分m,判断可行性

    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<iostream>
    using namespace std;
    const int MAXN = 5e2 + 10;
    const int MAXM = 1e4 + 10;
    int n, m;
    int vis[MAXN];
    int flag[MAXN]; // 所属强连通分量的拓扑序
    vector<int> G[MAXN], rG[MAXN]; // 注意初始化
    vector<int> vs; // 后序遍历顺序的顶点列表
    void addedge(int x, int y)
    {
        G[x].push_back(y);  // 正向图
        rG[y].push_back(x); // 反向图
    }
    void dfs(int u)
    {
        vis[u] = 1;
        for(int i = 0; i < G[u].size(); i++)
        {
            int v = G[u][i];
            if(!vis[v]) dfs(v);
        }
        vs.push_back(u);
    }
    void rdfs(int u, int k)
    {
        vis[u] = 1;
        flag[u] = k;
        for(int i = 0; i < rG[u].size(); i++)
        {
            int v = rG[u][i];
            if(!vis[v]) rdfs(v, k);
        }
    }
    int scc() // 强连通分量的个数
    {
        vs.clear();
        memset(vis, 0, sizeof vis);
        for(int i = 0; i < n; i++)
            if(!vis[i]) dfs(i);
        memset(vis, 0, sizeof vis);
        int k = 0;
        for(int i = vs.size() - 1; i >= 0; i--)
            if(!vis[vs[i]]) rdfs(vs[i], k++);
        return k;
    }
    bool judge()
    {
        int N = n;
        n = 2 * n;
        scc();
        n /= 2;
        for(int i = 0; i < N; i++)
            if(flag[i] == flag[N + i])
                return false;
        return true;
    }
    int a[MAXM], b[MAXM], c[MAXM];
    void init(int can)
    {
        for(int i = 0; i < 2 * n; i++) G[i].clear(), rG[i].clear();
        for(int i = 0; i <= can; i++) // 注意这里是等号
        {
            if(c[i] == 2) // A and B = 0
            {
                addedge(a[i], b[i] + n);
                addedge(b[i], a[i] + n);
            }
            else if(c[i] == 1) // A xor B = 0
            {
                addedge(a[i], b[i]);
                addedge(a[i] + n, b[i] + n);
                addedge(b[i], a[i]);
                addedge(b[i] + n, a[i] + n);
            }
            else // A or B != 0
            {
                addedge(a[i] + n, b[i]);
                addedge(b[i] + n, a[i]);
            }
        }
    }
    void solve()
    {
        int l = 0, r = m, mid;
        while(l + 1 < r)
        {
            mid = (l + r) / 2;
            init(mid);
            if(judge()) l = mid;
            else r = mid;
        }
        printf("%d
    ", l + 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], &b[i], &c[i]);
            solve();
        }
        return 0;
    }
    
  • 相关阅读:
    【springboot】@Valid参数校验
    【springboot】事务处理
    【springboot】过滤器、监听器、拦截器,Aspect切片
    【java web】过滤器、拦截器、监听器的区别
    【java web】监听器listener
    【java web】拦截器inteceptor
    【java web】过滤器filter
    【权限管理】Apache Shiro和Spring Security的对比
    【面试题】挑战10个最难回答的Java面试题(附答案)
    【面试题】反向面试
  • 原文地址:https://www.cnblogs.com/ftae/p/6791333.html
Copyright © 2011-2022 走看看