zoukankan      html  css  js  c++  java
  • hdu 5215 Cycle

    题意:找到一个图中是否含有奇环和偶环

    题解:

    1.用了两种发法。一个就是跟bc给的答案一样,先求弱联通分量。再在环中找奇偶环

    2.我想到的一个略微省些代码量的方法。边求联通分量,边推断是否含有奇环偶环。奇环一定能推断出来,可是偶环

    能被两个奇数环取代而没有在遍历中发现

    3.解决问题用到鸽巢定理。先推断有n个联通分量。假设有m个奇环(m > n)则一定有两个奇环在一个连通分量

    中,两个奇环可以变成一个偶环,(有个地方须要注意就是:对于单点。当作是一个奇环处理)。

    总结:

    1.開始想到的解题方法跟标答一样,认为并非特别难,写代码的时候感觉特别困。迷迷糊糊的写完了就WA了,睡醒

    后,又一次一句一句检查代码,感觉状态不好的时候写的代码简直就是恶心,错误百出,以后状态不好的时候直接休

    2.后来想到这个优化的方法,写了也WA,第二天才发现题目读错了。这个图可能不是联通的,第一种方法的错误代码

    居然ac了,感觉以后千万不要死扣一个错误,找不到就做会别的事情。再回过头来继续找的时候。也不要局限于一个

    范围。着眼于全局查错!

    第一种标答方法:

    #pragma comment(linker, "/STACK:102400000,102400000")
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define MAXN 100005
    #define MAXM 300005
    int n,m,_,e,top,cnt,bcc,odd,even,ans1,ans2;
    int first[MAXN],dfn[MAXN],stack[MAXN];
    int id[MAXN],color[MAXN],vis[MAXN];
    struct Edge
    {
        int next,v;
    }edge[MAXM << 1];
    void insert(int u,int v)
    {
        edge[e].v = v;
        edge[e].next = first[u];
        first[u] = e++;
    }
    void bipartite(int u,int bcc)
    {
        for(int i = first[u];i != -1;i = edge[i].next)if(!vis[i] && !vis[i ^ 1])
        {
            int v = edge[i].v;
            if(id[v] != bcc)continue;
            vis[i] = vis[i ^ 1] = true;
            if(color[v] && color[u] != color[v])even++;
            if(color[u] == color[v])odd++;
            else if(!color[v])
            {
                color[v] = 3 - color[u];
                bipartite(v,bcc);
            }
        }
    }
    void search(int bcc,int u)
    {
        even = odd = 0;
        color[u] = 1;
        bipartite(u,bcc);
        if(odd > 1)even = true;
        ans1 = max(odd,ans1);
        ans2 = max(ans2,even);
    }
    int dfs(int u,int fa)
    {
        int lowu = dfn[u] = ++cnt;
        stack[++top] = u;
        for(int i = first[u];i != -1;i = edge[i].next)if((i ^ 1) != fa)
        {
            int v = edge[i].v;
            if(!dfn[v])
            {
                int lowv = dfs(v,i);
                lowu = min(lowu,lowv);
                if(dfn[u] < lowv)
                {
                    bcc++;
                    do
                    {
                        id[stack[top--]] = bcc;
                    }while(stack[top + 1] != v);
                }
            }
            else lowu = min(lowu,dfn[v]);
        }
        return lowu;
    }
    void solve()
    {
        ans1 = ans2 = 0;
        memset(dfn,0,sizeof(dfn));
        memset(color,0,sizeof(color));
        memset(id,0,sizeof(id));
        memset(vis,0,sizeof(vis));
        bcc = cnt = top = 0;
        for(int i = 1;i <= n;i++)if(!dfn[i])dfs(1,-1);
        for(int u = 1;u <= n;u++)
            if(!color[u])
            {
                search(id[u],u);
                if(ans1 && ans2)return;
            }
    }
    int main()
    {
        scanf("%d",&_);
        while(_--)
        {
            scanf("%d%d",&n,&m);
            memset(first,-1,sizeof(first));
            e = 0;
            for(int i = 0;i < m;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                insert(u,v),insert(v,u);
            }
            solve();
            if(ans1)puts("YES");
            else puts("NO");
            if(ans2)puts("YES");
            else puts("NO");
        }
    }
    

    优化后的方法:

    #pragma comment(linker, "/STACK:102400000,102400000")
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define MAXN 100005
    #define MAXM 300005
    int n,m,_,e,top,cnt,bcc,odd,even,point;
    int first[MAXN],dfn[MAXN],stack[MAXN],color[MAXN];
    bool vis[MAXM << 1];
    struct Edge
    {
        int next,v;
    }edge[MAXM << 1];
    void insert(int u,int v)
    {
        edge[e].v = v;
        edge[e].next = first[u];
        first[u] = e++;
    }
    int dfs(int u)
    {
        int lowu = dfn[u] = ++cnt;
        stack[++top] = u;
        for(int i = first[u];i != -1;i = edge[i].next)if(!vis[i] && !vis[i ^ 1])
        {
            int v = edge[i].v;
            vis[i] = vis[i ^ 1] = true;
            if(color[v] + color[u] == 3)even++;
            if(color[u] == color[v])odd++;
            if(!dfn[v])
            {
                color[v] = 3 - color[u];
                int lowv = dfs(v);
                lowu = min(lowu,lowv);
                if(dfn[u] < lowv)
                {
                    bcc++;
                    int num = 0;
                    do
                    {
                        num++;
                    }while(stack[top--] != v);
                    if(num == 1)point++;
                }
            }
            else lowu = min(lowu,dfn[v]);
        }
        return lowu;
    }
    void solve()
    {
        even = odd = point = 0;
        memset(dfn,0,sizeof(dfn));
        memset(color,0,sizeof(color));
        memset(vis,false,sizeof(vis));
        bcc = 0;
        cnt = top = 0;
        for(int i = 1;i <= n;i++)if(!dfn[i])
        {
            bcc++;
            color[i] = 1;
            dfs(i);
        }
        if(top == 1)point++;
        if(point + odd > bcc)even++;
    }
    int main()
    {
        scanf("%d",&_);
        while(_--)
        {
            scanf("%d%d",&n,&m);
            memset(first,-1,sizeof(first));
            e = 0;
            for(int i = 0;i < m;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                insert(u,v),insert(v,u);
            }
            solve();
            if(odd)puts("YES");
            else puts("NO");
            if(even)puts("YES");
            else puts("NO");
        }
    }
    


  • 相关阅读:
    css设置兼容的透明样式
    mybatis 使用oracle merge into 语句踩坑实录
    eclipse导入SVN上的Maven多模块项目
    jquery.form插件中动态修改表单数据
    java的几种对象(po,dto,dao等)
    redis面试总结
    前段面试准备
    查询各科成绩最好的学生
    Github访问慢解决办法
    该文件有程序在使用
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/6722853.html
Copyright © 2011-2022 走看看