hdu 5215 Cycle

来源:互联网 发布:马爹利鼎盛干邑 知乎 编辑:程序博客网 时间:2024/05/16 02:03

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

题解:

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 300005int 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 300005int 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");    }}


0 0
原创粉丝点击