zoukankan      html  css  js  c++  java
  • CF36 E Two Paths——欧拉(回)路

    题目:http://codeforces.com/contest/36/problem/E

    给定一张无向图,要求输出两条欧拉路覆盖所有边;

    分类讨论,首先判-1:有两个以上连通块 / 有四个以上奇度数点 / 只有一条边 / 有两个连通块而其中一个连通块里有四个奇度数点 (/ 有连通块里有奇数个奇度数点);

    然后分两个连通块和一个连通块的情况进行 dfs 找欧拉路(模板 dfs );

    注意可能没有奇度数的点,也就是有欧拉回路,所以不仅找奇度数点进行 dfs ,还要在那之后 dfs 仍然没有被走过的点;

    明明是模仿题解写的竟然还调了两小时...码力++...

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int const maxn=10005;
    int n,m,d[maxn],ans[maxn],tot,fa[maxn],cnt,c[maxn],hd[maxn],ct=1;
    bool vis[maxn],used[maxn];
    struct N{
        int to,nxt;
        N(int t=0,int n=0):to(t),nxt(n) {}
    }ed[maxn<<1];
    void add(int x,int y){ed[++ct]=N(y,hd[x]); hd[x]=ct;}
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    void dfs(int x)
    {
        vis[x]=1;
        for(int i=hd[x];i;i=hd[x])
        {
            hd[x]=ed[i].nxt;
            if(used[i>>1])continue;
            used[i>>1]=1; dfs(ed[i].to); ans[++tot]=(i>>1);
        }
    }
    int main()
    {
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        n=10000; scanf("%d",&m);//不能是 n=10005
        for(int i=1;i<=n;i++)fa[i]=i;//!!
        for(int i=1,x,y;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y); add(y,x); d[x]++; d[y]++;
            if(find(x)!=find(y))fa[find(x)]=find(y);
        }
        for(int i=1;i<=n;i++) if(d[i]&1) c[find(i)]++;
        for(int i=1;i<=n;i++) if(c[i]&1){printf("-1
    "); return 0;}
        for(int i=1,sum=0;i<=n;i++)
        {
            if(d[i])cnt+=(i==find(i));
            if(c[i])sum+=c[i];
            if(sum>4){printf("-1
    "); return 0;}
        } 
        if(cnt>2){printf("-1
    "); return 0;}
        if(cnt==2)
        {
            for(int i=1;i<=n;i++) if(c[i]==4){printf("-1
    "); return 0;}
            for(int i=1;i<=n;i++)
                if(!vis[i]&&(d[i]&1))
                {
                    tot=0; dfs(i); printf("%d
    ",tot);
                    for(int j=tot;j;j--)printf("%d ",ans[j]); printf("
    ");
                }
            for(int i=1;i<=n;i++)//欧拉回路 
                if(!vis[i]&&d[i])
                {
                    tot=0; dfs(i); printf("%d
    ",tot);
                    for(int j=tot;j;j--)printf("%d ",ans[j]); printf("
    ");
                }
        }
        else
        {
            bool fl=0;
            for(int i=1;i<=n;i++) if(c[i]==4)fl=1;
            if(fl)
            {
                for(int i=1;i<=n;i++)    if(d[i]&1)
                {
                    for(int j=i+1;j<=n;j++)
                        if(d[j]&1){d[i]++; d[j]++; add(i,j); add(j,i); break;}
                    break;
                }
                for(int i=1;i<=n;i++)
                    if(!vis[i]&&(d[i]&1)){tot=0; dfs(i); break;}
                for(int i=1;i<=tot;i++)    if(ans[i]==m+1)
                {
                    printf("%d
    ",i-1);
                    for(int j=1;j<i;j++)printf("%d ",ans[j]); printf("
    ");
                    printf("%d
    ",tot-i);
                    for(int j=i+1;j<=tot;j++)printf("%d ",ans[j]);
                    break;
                }
            }
            else
            {
                for(int i=1;i<=n;i++)
                    if(!vis[i]&&(d[i]&1)){tot=0; dfs(i);}
                for(int i=1;i<=n;i++)//欧拉回路 
                    if(!vis[i]&&d[i]){tot=0; dfs(i);}
                if(tot<=1){printf("-1
    "); return 0;}//只有一条边 
                printf("1
    %d
    %d
    ",ans[1],tot-1);
                for(int i=2;i<=tot;i++)printf("%d ",ans[i]);
            }
        }
        return 0;
    }
  • 相关阅读:
    MJRefreshFooterView
    UIActionSheet
    UIAlertView带textField
    SIAlertView
    旋转 锚点
    centos7.2 Apache+PHP7.2+Mysql5.6环境搭建
    ubuntu16.04 mysql 开启远程连接
    Ubuntu16.04重新安装MySQL数据库
    Ubuntu16.04彻底卸载MySQL
    laravel框架基础(2)---laravel项目加载机制
  • 原文地址:https://www.cnblogs.com/Zinn/p/9279336.html
Copyright © 2011-2022 走看看