zoukankan      html  css  js  c++  java
  • poj2723 2分 + 2-sat

      这道题的意思是给你n对钥匙, 编号0 - 2*n-1, 有m对门每个门后面有两个锁一个钥匙只能开一把锁, 并且一对钥匙中如果使用了一把锁, 那么另外一把就不能再使用,每个门后面的锁可能会一样, 根据钥匙我们可以发现这是个2-sat问题,门告诉我们那两个钥匙不能共存, 如果门后面的锁一样的话则必须选择这个钥匙, 代码如下:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    
    using namespace std;
    const int maxn = (1<<11)+100;
    int N, M;
    struct Key
    {
        int a, b;
    }ke[maxn];
    int f[maxn];
    struct Door
    {
        int a, b;
    
    }Do[maxn];
    
    struct Scc
    {
        int V;
        vector<int> G[maxn];   //原始图
        vector<int> rG[maxn];  //反向边
        vector<int> vs;        //后序遍历顶点列表
        bool used[maxn];       //访问标记
        int cmp[maxn];         //所属强连通分量
        void init()
        {
            for(int i=0; i<=V; i++) G[i].clear(), rG[i].clear();
        }
        void add_edge(int from, int to)
        {
            G[from].push_back(to);
            rG[to].push_back(from);
        }
        void dfs(int v)
        {
            used[v] = true;
            for(int i=0; i<G[v].size(); i++)
                if(!used[G[v][i]]) dfs(G[v][i]);
            vs.push_back(v);
        }
        void rdfs(int v, int k)
        {
            used[v] = true;
            cmp[v] = k;
            for(int i=0; i<rG[v].size(); i++)
                if(!used[rG[v][i]]) rdfs(rG[v][i], k);
        }
        int scc()
        {
            memset(used, 0, sizeof(used));
            vs.clear();
            for(int v=1; v<=V; v++)
                if(!used[v]) dfs(v);
            memset(used, 0, sizeof(used));
            int k = 1;
            for(int i=vs.size()-1; i>=0; i--)
                if(!used[vs[i]]) rdfs(vs[i], k++);
            return k-1;
        }
    }ss;
    
    bool check(int mid)
    {
        ss.V = 2*N;
        ss.init();
        for(int i=0; i<mid; i++)
            if(Do[i].a != Do[i].b)       //不一样时的情况
            {
                ss.add_edge(Do[i].a, f[Do[i].b]);
                ss.add_edge(Do[i].b, f[Do[i].a]);
            }
            else
                ss.add_edge(f[Do[i].a], Do[i].a);   //一样的时候必须选
        ss.scc();
        bool res = true;
        for(int i=0; i<N; i++)
        {
            int u=ke[i].a, v=ke[i].b;
            if(ss.cmp[u]==ss.cmp[v])
            {
                res = false;
                break;
            }
        }
        return res;
    }
    
    int main()
    {
        while(scanf("%d%d", &N, &M)==2)
        {
            if(N==0 && M==0) break;
            for(int i=0; i<N; i++)
            {
                int a, b;
                scanf("%d%d", &a, &b);
                f[a] = b; f[b] = a;
                ke[i] = (Key){a, b};
            }
            for(int i=0; i<M; i++)
            {
                int a, b;
                scanf("%d%d", &a, &b);
                Do[i] = (Door){a, b};
            }
            int l=0, r=M;
            int ans;
            while(l <= r)
            {
                int mid = (l+r)/2;
                bool tp = check(mid);
                //printf("l=%d, r=%d, mid=%d, tp=%d
    ", l, r, mid, tp);
                if(tp)
                {
                    ans = mid;
                    l = mid+1;
                }
                else r = mid-1;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    zookeeper基础
    4. Zookeeper单机版安装
    3. 服务中间件Dubbo
    2. Maven工程的搭建
    Maven的优点
    应用架构的演进历史 MVC、 RPC、SOA 和 微服务架构
    js 正则表达式验证
    后台正则表达式验证部分部分总结
    Linux下记录登录用户历史操作
    Django使用Ace实现在线编辑器
  • 原文地址:https://www.cnblogs.com/xingxing1024/p/5235341.html
Copyright © 2011-2022 走看看