zoukankan      html  css  js  c++  java
  • cf 36e Two Paths

    此题标难度2500,场内ac4人,因为是一开始的cf,段位都不高就给的分低了。可能有2700分。
    欧拉路径好题
    题意:给你一个无向图,问能否输出两条路径,使得遍历所有边。
    思路:很显然,一眼能想到欧拉路径,但是两条看似简单,其实要想很多。

    1. m==1 此时输出-1
    2. 只有一个联通块,那么我们仔细想一下,当度数为0,2,4的时候是可以的,0 和 2很显然。但4怎么搞,这是一个这道题比较难也比较亮的一点。我的做法是给两个奇度加边,然后输出的时候隔离这个加边。那么我们来证明一下吧,无向图的欧拉路径只要满足a. 联通 b. 奇度为0,和奇度为2,此时可以。那么我们输出两条路径,等价于我们把4个奇度两个相连变为一个2奇度的图,然后跑欧拉路径,之后只要隔离这条边就行了。
    3. 两个联通块,每个块度数为0,2时可以。
      有个大佬用图解的方法写出来了:https://www.luogu.org/blog/user56917/solution-cf36e
      我的代码:
    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    const int maxn = 1e4+5;
    //vector<int>zz;
    int head[maxn],deg[maxn],ans[maxn],vis[maxn],tot,sum,cnt,cnt2;
    bool a[maxn];
    struct edge{
        int v,nex;
        bool ok;
    }e[maxn<<1];
    void init(){
        forn(i,maxn) head[i] = -1;
        tot = 0;
    }
    void add(int u,int v){
        e[tot] = {v,head[u],0};
        head[u] = tot++;
    }
    void dfs(int u){
        vis[u] = cnt;
        //cerr<<"@!#!@ "<<u<<' '<<cnt<<'
    ';
        for(int i = head[u];i!=-1;i = e[i].nex){
            int v = e[i].v;
            if(!vis[v]) dfs(v);
        }
    }
    void euler(int u){
        for(int i = head[u];i!=-1;i = e[i].nex){
            int v = e[i].v;
            if(e[i].ok) continue;
            e[i].ok = 1,e[i^1].ok = 1;
            euler(v);
            //cerr<<"asdas        "<<u<<' '<<v<<'
    ';
            ans[++sum] = i+2>>1;
        }
        //zz.push_back(u);
    }
    int main(){
        IO;
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        init();
        int m;cin>>m;
        if(m==1) return cout<<-1<<'
    ',0;
        forn(i,m){
            int u,v;cin>>u>>v;
            deg[u]++,deg[v]++;
            //cerr<<deg[u]<<' '<<deg[v]<<'
    ';
            a[u] = a[v] = 1;
            add(u,v),add(v,u);
        }
        for1(i,maxn-5) if(!vis[i]&&a[i]) cnt++,dfs(i);
        if(cnt>2) return cout<<-1<<'
    ',0; 
        if(cnt==1){
            cnt = 0;
            for1(i,maxn-5) if(deg[i]&1) cnt++; 
            if(cnt!=2&&cnt!=4&&cnt!=0) return cout<<-1<<'
    ',0; 
            if(cnt==0){
                for1(i,maxn-5) if(a[i]) {
                    euler(i);
                    break;
                }
                cout<<m-1<<'
    ';
                for(int i = m;i>1;i--) cout<<ans[i]<<' ';
                cout<<'
    ';
                cout<<1<<'
    ';
                cout<<ans[1]<<'
    ';
            }else if(cnt==2){
                for1(i,maxn-5) if(deg[i]&1){
                    euler(i);
                    break;
                }
                cout<<m-1<<'
    ';
                //cerr<<"!@#@!#  "<<sum<<' '<<m<<'
    ';
                for(int i = m;i>1;i--) cout<<ans[i]<<' ';
                cout<<'
    ';
                cout<<1<<'
    ';
                cout<<ans[1]<<'
    ';
            }else{
                vector<int>odd;
                for1(i,maxn-5) if(deg[i]&1) odd.push_back(i);
                add(odd[1],odd[2]); 
                add(odd[2],odd[1]);
                //cerr<<odd[0]<<'
    ';
                euler(odd[0]);
                //cerr<<"!@##@!  "<<sum<<' '<<m<<'
    ';
                //reverse(zz.begin(),zz.end());
                //for(auto &x:zz) cerr<<x<<' ';
               // cerr<<'
    ';
                while(1){
                    if(ans[sum]>m) break;
                    sum--;
                }
                cout<<m+1-sum<<'
    ';
                for(int i = m+1;i>sum;i--) cout<<ans[i]<<' ';
                sum--;
                cout<<'
    ';
                cout<<sum<<'
    ';
                for(int i = sum;i>=1;i--) cout<<ans[i]<<' ';
            }
            return 0;
        }
        //cerr<<"@!#!@# "<<'
    '; 
        cnt = 0;
        for1(i,maxn) if(deg[i]&1){
            //cerr<<"!@#!@# "<<i<<' '<<vis[i]<<'
    ';
            if(vis[i]==1) cnt++;
            else cnt2++;
        }
        //cerr<<cnt<<' '<<cnt2<<'
    ';
        if(cnt!=0&&cnt!=2) return cout<<-1<<'
    ',0; 
        if(cnt2!=0&&cnt2!=2) return cout<<-1<<'
    ',0;
        if(cnt==0){
            for1(i,maxn) if(vis[i]==1){
                euler(i);
                break;
            }
        }else{
            for1(i,maxn) if((deg[i]&1)&&vis[i]==1){
                euler(i);
                //cerr<<"@!#@# "<<i<<'
    ';
                break;
            }
        }
        cout<<sum<<'
    ';
        for(int i = sum;i>=1;i--) cout<<ans[i]<<' ';
        cout<<'
    ';
        sum = 0;
        if(cnt2==0){
            for1(i,maxn) if(vis[i]==2){
                euler(i);
                break;
            }
        }else{
            for1(i,maxn) if((deg[i]&1)&&vis[i]==2){
                euler(i);
                break;
            }
        }
        cout<<sum<<'
    ';
        for(int i = sum;i>=1;i--) cout<<ans[i]<<' ';
        cout<<'
    ';
        return 0;
    }
    /*
    9
    1 2
    2 3
    3 4
    4 5
    5 2
    4 6
    6 7
    7 8
    8 6
    */
    
  • 相关阅读:
    ecolise 设置反编译
    整理03
    JAVA创建对象的五种方式
    JAVA中的深复制和浅复制--建议多看几遍
    选择题
    python学习第九天
    python学习第八天
    python学习第七天
    python学习第五天
    python学习第四天
  • 原文地址:https://www.cnblogs.com/AlexPanda/p/12520291.html
Copyright © 2011-2022 走看看