• poj2723


    poj2723

    题意

    m道门,每道门两把锁,有n对钥匙,对应2*n把锁,已知一对钥匙内取出一把另一把就会消失,求按顺序最多可开多少门 。

    分析

    任意一道门都是一个子句,两把锁A和B是OR的关系。即 A OR B = 1 <=> !A->B AND !B->A

    二分最大可以开门的数量,判断可行性。

    code

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    using namespace std;
    typedef long long ll;
    
    const int INF = 1e9;
    const int MAXN = 3e3 + 5;
    int vis[MAXN], flag[MAXN];
    vector<int> G[MAXN], rG[MAXN];
    vector<int> vs;
    int n, m;
    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;
    }
    
    int deny[MAXN], a[MAXN], b[MAXN];
    bool judge()
    {
        int N = n;
        n = 2 * n;
        scc();
        n /= 2;
        for(int i = 0; i < 2 * n; i++)
            if(flag[i] == flag[deny[i]]) return false;
        return true;
    }
    int solve()
    {
        int l = 0, r = m, mid;
        while(l < r)
        {
            mid = (l + r) / 2;
            memset(G, 0, sizeof G);
            memset(rG, 0, sizeof rG);
            for(int i = 0; i <= mid; i++)
            {
                addedge(deny[a[i]], b[i]);
                addedge(deny[b[i]], a[i]);
            }
            if(judge()) l = mid + 1;
            else r = mid;
        }
        return l;
    }
    int main()
    {
        while(~scanf("%d%d", &n, &m) && (n + m))
        {
            for(int i = 0; i < n; i++)
            {
                int x, y;
                scanf("%d%d", &x, &y);
                deny[x] = y; deny[y] = x;
            }
            for(int i = 0; i < m; i++)
                scanf("%d%d", &a[i], &b[i]);
            printf("%d
    ", solve());
        }
        return 0;
    }
    
  • 相关阅读:
    理清一下JavaScript面向对象思路
    IE的CSS渲染跟其它浏览器有什么不同
    页面元素的CSS渲染优先级
    push与createElement性能比较
    关于JavaScript的push()函数
    关于JavaScript的沙箱模式
    JavaScript SandBox沙箱设计模式
    用live()方法给新增节点绑定事件
    深入JavaScript对象创建的细节
    Keras class_weight和sample_weight用法
  • 原文地址:https://www.cnblogs.com/ftae/p/6791313.html
Copyright © 2020-2023  润新知