zoukankan      html  css  js  c++  java
  • SP2878 KNIGHTS

    KNIGHTSKNIGHTS

    题目描述见链接 .


    color{red}{正解部分}

    将原图的 补图 建出,
    那么当一个节点被某个奇环覆盖时, 就存在一个方案, 使得这个节点参加会议 .
    当得到所有被至少一个奇环覆盖的节点数量 cntcnt 后, 使用 总结点数量 减去 cntcnt 即可得到答案 .
    那么现在的问题就是 cntcnt 如何求,

    首先要知道 22 个引理 downarrow

    • 不同 点双联通分量 之间不会被同一个 奇环 覆盖 .

    若存在一个奇环沟通两个 点双联通分量, 那么这两个 点双联通分量 可以合并 .

    • 在一个 点双联通分量 中, 若存在一个 奇环, 则所有点被至少一个 奇环 覆盖 .

    设在 点双联通分量 中的 奇环 中存在两个点 u,vu, v, 奇环 外部存在一个点 ww, 由于 奇环u,vu, v 存在两条 奇偶性 不同的路径, u,v,wu,v,w 可以构成 奇环偶环 .

    知道这 22 个引理之后, 就可以做这道题目了 .

    使用 TarjanTarjan 缩点, 判断每个 点双联通分量 中是否存在奇环即可, 二分图 中不存在 奇环, 二染色 来判断是否 二分图 即可 .


    color{red}{实现部分}

    #include<bits/stdc++.h>
    #define reg register
    #define pb push_back
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    const int maxn = 1005;
    
    int N;
    int M;
    int tim;
    int Ans;
    int num0;
    int bk_cnt;
    int low[maxn];
    int dfn[maxn];
    int head[maxn];
    int bk_Mp[maxn];
    int color[maxn];
    
    bool Used[maxn];
    bool In_stk[maxn];
    bool is[maxn][maxn];
    
    std::stack <int> stk;
    std::stack <int> stk_2;
    
    std::vector <int> bk[maxn];
    
    struct Edge{ int nxt, to; } edge[maxn*maxn<<1];
    
    void Add(int from, int to){ edge[++ num0] = (Edge){ head[from], to }; head[from] = num0; }
    
    void Tarjan(int k, int fa){
            low[k] = dfn[k] = ++ tim; 
            for(reg int i = head[k]; i; i = edge[i].nxt){
                    int to = edge[i].to;
                    if(!dfn[to]){
                            stk.push(k), stk_2.push(to);
                            Tarjan(to, k), low[k] = std::min(low[k], low[to]);
                            if(low[to] < dfn[k]) continue ;
                            bk_cnt ++;
                            while(!stk.empty()){
                                    int tp = stk.top(), tu = stk_2.top();
                                    bk[bk_cnt].pb(tp), bk[bk_cnt].pb(tu);
                                    stk.pop(), stk_2.pop();
                                    if(tp == k && tu == to) break ;
                            }
                    }else if(dfn[to] < dfn[k] && to != fa){
                            stk.push(k), stk_2.push(to);
                            low[k] = std::min(low[k], dfn[to]);
                    }
            }
    }
    
    int col_cnt;
    
    bool DFS(int k, int col, int id){
            color[k] = col;
            for(reg int i = head[k]; i; i = edge[i].nxt){
                    int to = edge[i].to;
                    if(id != bk_Mp[to]) continue ;
                    if(color[k] == color[to]) return false;
                    if(color[to] == -1){
                            color[to] = col ^ 1;
                            if(!DFS(to, col^1, id)) return false;
                    }
            }
            return true;
    }
    
    void Work(){
            tim = num0 = 0;
            for(reg int i = 1; i <= N; i ++) Used[i] = head[i] = dfn[i] = 0, color[i] = -1;
            for(reg int i = 1; i <= N; i ++)
                    for(reg int j = 1; j <= N; j ++) is[i][j] = 0;
            for(reg int i = 1; i <= M; i ++){
                    int a = read(), b = read();
                    is[a][b] = is[b][a] = 1;
            }
            for(reg int i = 1; i <= N; i ++)
                    for(reg int j = i+1; j <= N; j ++)
                            if(!is[i][j]) Add(i, j), Add(j, i);
            for(reg int i = 1; i <= N; i ++) if(!dfn[i]) Tarjan(i, 0);
            for(reg int i = 1; i <= bk_cnt; i ++){
                    memset(color, -1, sizeof color);
                    for(reg int j = 0; j < bk[i].size(); j ++) bk_Mp[bk[i][j]] = i;
                    if(!DFS(bk[i][0], 0, i))
                            for(reg int j = 0; j < bk[i].size(); j ++) Used[bk[i][j]] = 1;
                    bk[i].clear();
            }
            Ans = N;
            for(reg int i = 1; i <= N; i ++) Ans -= Used[i];
            printf("%d
    ", Ans);
    }
    
    int main(){
            N = read(), M = read();
            while(N && M){
                    Work();
                    N = read(), M = read();
            }
            return 0;
    }
    
  • 相关阅读:
    Android 使用Fragment,ViewPagerIndicator 制作csdn app主要框架
    关于activity_main.xml与fragment_main.xml
    在MAC OS 下配置python + Flask ,并支持pyCharm编辑器
    openshift云计算平台diy模式安装Python2.7+Flask
    flask程序部署在openshift上的一些注意事项
    windows下python+flask环境配置详细图文教程
    SegmentFault 2014黑客马拉松 北京 作品demo
    Flask —— 使用Python和OpenShift进行即时Web开发
    支付宝的简单使用
    iOS- 详解文本属性Attributes
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822481.html
Copyright © 2011-2022 走看看