zoukankan      html  css  js  c++  java
  • bzoj2841

    边双联通分量

    具体详解蓝书上十分详细,因为必须是奇数个人坐在一起,那么一个人如果能选上,就必须处在一个简单奇圈中。而奇圈也是一个边双联通分量,所以我们先把边双联通分量都挖出来,然后进行二分图染色。

    奇圈不能被二分图染色,所以标记所有不能被染色的点,减去就是答案

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    int n, top, cnt, tot, color, ans, m;
    int dfn[N], low[N], st[N], vis[N], col[N], mark[N], head[N];
    struct edge {
        int nxt, to;
    } e[N << 4];
    vector<int> G[N];
    void link(int u, int v)
    {
        e[++cnt].nxt = head[u];
        head[u] = cnt;
        e[cnt].to = v;
    }
    void tarjan(int u, int last)
    {
        dfn[u] = low[u] = ++tot; st[++top] = u;
        for(int i = head[u]; i; i = e[i].nxt) if(e[i].to != last)
        {
            if(!dfn[e[i].to])
                tarjan(e[i].to, u);
            if(dfn[e[i].to] != -1)
                low[u] = min(low[u], low[e[i].to]);
        }
        if(low[u] == dfn[u])
        {
            ++color;
            while(st[top + 1] != u)
            {
                dfn[st[top]] = -1;
                col[st[top]] = color;
                --top; 
            }
        }
    }
    bool dfs(int u, int c)
    {
        vis[u] = c;
        for(int i = 0; i < G[u].size(); ++i)
        {
            int v = G[u][i];
            if(vis[v] == c) return false;
            if(!vis[v]) 
                if(!dfs(v, c ^ 1)) 
                    return false;
        }
        return true;
    }
    int main()
    {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= m; ++i)
        {
            int u, v; scanf("%d%d", &u, &v);
            link(u, v);
            link(v, u);
        }
        for(int i = 1; i <= n; ++i) 
            if(!dfn[i])
                tarjan(i, 0);
        for(int i = 1; i <= n; ++i)
            for(int j = head[i]; j; j = e[j].nxt)
                if(col[e[j].to] == col[i])
                {
                    G[e[j].to].push_back(i);
                    G[i].push_back(e[j].to);
                } 
        memset(vis, -1, sizeof(vis));
        for(int i = 1; i <= n; ++i)
            if(vis[i] == -1 && !dfs(i, 0)) 
                mark[col[i]] = 1;
        ans = n;
        for(int i = 1; i <= n; ++i)
            if(mark[col[i]])
                --ans;
        printf("%d
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    docker 安装 nexus3 初始密码不再是admin123
    eclipse中Tomcat修改项目名称
    WAMP3.1.3自定义根目录
    git学习笔记
    小米和MAC触摸板手势汇总
    IDEA快捷键汇总
    servelet 实现Post接口访问
    LeetCode:Jump Game II
    LeetCode:Trapping Rain Water
    LeetCode: Container With Most Water
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7053812.html
Copyright © 2011-2022 走看看