• [2020多校联考]组合


    2020.11.21

    解法

    把每种字符看成一个点,把每个简单词看成一条边((T=1) 时是无向边,(T=2) 时是有向边)。那么问题就转换为寻找一条路径,使得该路径不重复地走过所有边,即寻找欧拉路径。

    一张无向图包含欧拉路径,当且仅当所有点的度数为偶或者恰好有两个度数为奇的节点。一张无向图包含欧拉回路,当且仅当所有点度数为偶。一张有向图包含欧拉路径,当且仅当所有点的入度和出度相等或者恰好有一个节点的出度等于入度加一且又一个节点的入度等于出度加一。一张有向图包含欧拉回路,当且仅当所有点的入度和出度相等。

    按以上判定,若有欧拉路,直接dfs,在遍历某条边结束的时候将该边加入栈,最后弹栈输出栈内元素。加上当前弧优化,复杂度 (O(N+M))

    #include<stdio.h>
    #include<string.h>
    #define N 100007
    #define M 200007
     
    inline int read(){
        int x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
     
    struct E{
        int next,to,p;
        bool vis;
    }e[M<<1];
    int T,n,m,in[N],out[N],d[N];
    int head[N],cnt=0;
     
    inline void add(int id,int to,int p){
        e[++cnt]=(E){head[id],to,p,0};
        head[id]=cnt;
    }
     
    inline int min(int x,int y){return x<y? x:y;}
    int ans[M],top=0,p[M];
    void dfs1(int u){
        for(int i=head[u];~i;i=min(head[u],e[i].next)){
            if(e[i].vis) continue;
            e[i].vis=e[i^1].vis=1;
            head[u]=e[i].next;
            dfs1(e[i].to);
            ans[++top]=e[i].p;
        }
    }
     
    void dfs2(int u){
        for(int i=head[u];i;i=min(head[u],e[i].next)){
            if(e[i].vis) continue;
            e[i].vis=1;
            head[u]=e[i].next;
            dfs2(e[i].to);
            ans[++top]=e[i].p;
        }
    }
     
    void print(){
        printf("YES
    ");
        for(int i=top;i;i--)
            if(ans[i]) printf("%d ",ans[i]);
    }
     
    int main(){
        T=read(),m=read(),n=read();
        if(!n) printf("YES
    ");
        else if(T==1){
            cnt=-1;
            memset(head,-1,sizeof(head));
            for(int i=1;i<=n;i++){
                int u=read(),v=read();
                add(u,v,i),add(v,u,-i);
                d[u]++,d[v]++;
            }
            while(head[p[1]]==-1) p[1]++;
            int tag=0;
            for(int i=1;i<=m;i++)
                if(d[i]&1) p[++tag]=i;
            if(!tag||tag==2){
            //  if(tag) add(p[2],p[1],0),add(p[1],p[2],0);
                dfs1(p[1]);
                if(top==n) print();
                else printf("NO
    ");
            }else printf("NO
    ");
        }else{
            for(int i=1;i<=n;i++){
                int u=read(),v=read();
                add(u,v,i);
                in[v]++,out[u]++;
            }
            while(!head[p[1]]) p[1]++;
            bool tag1=0,tag2=0,tag3=0;
            for(int i=1;i<=m;i++){
                if(in[i]==out[i]) continue;
                if(!tag1&&in[i]==out[i]+1) tag1=1,p[2]=i;
                else if(!tag2&&in[i]==out[i]-1) tag2=1,p[1]=i;
                else tag3=1;
            }
            if(tag3||(tag1^tag2)) printf("NO
    ");
            else{
            //  if(tag) add()
                dfs2(p[1]);
                if(top==n) print();
                else printf("NO
    ");
            }
        }
    }
    
  • 相关阅读:
    《计算机图形学-基于3D图形开发技术》读书笔记
    【转】OpenGL和D3D 矩阵对比
    【转】D3D中详细拾取操作
    根据点坐标改变字体显示位置
    静态常量和常量在类中的初始化
    MFC单文档中使用D3D9
    单文档切换OpenGL视图
    超大地形的处理 (Terrain Visualization)【转自知乎】
    又出现这种问题。。。
    属性
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14024151.html
Copyright © 2020-2023  润新知