• LOJ 10105. 欧拉回路


    补题地址
    欧拉回路模板题。
    思路
    这个的关键是:当我们用链式前向星存图时,读第 i 条边(x, y)
    如果是无向边:(x,y) 边存的编号是(i - 1) * 2,反向边 (y,x) 边的编号是(i - 1) * 2 + 1。
    如果是单向边:(x,y) 边的编号是 i - 1。

    所以如果是有向图,&i=head[u]是引用 i = head[u], 来达到修改 head[u] 的目的, 这样走过的边不会再处理,是弧优化。
    如果是无向图,把vis[i ^ 1]标记为1,这样就不会再访问了,并且有弧优化,所以可以保证不会把走过的边再走一遍。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #include<queue>
    #include<vector>
    #include<string>
    #include<bitset>
    #include<fstream>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i);
    #define per(i, a, n) for(int i = n; i >= a; -- i);
    typedef long long ll;
    typedef pair<int,int> PII;
    const int N = 1e6 + 105;
    const int mod = 1e9 + 7;
    const double Pi = acos(- 1.0);
    const int INF = 0x3f3f3f3f; 
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    // bool cmp(int a, int b){return a > b;}
    //
    
    
    int n, m, type;
    int head[N], cnt = 0;
    int to[N << 1], nxt[N << 1];
    int in[N], out[N];
    bool vis[N];
    int res[N], tot = 0;
    
    void add(int u, int v){
        to[cnt] = v, nxt[cnt] = head[u], head[u] = cnt ++;
    }
    
    void dfs(int u){
        for(int &i = head[u]; i != -1; ){
            if(vis[i]){
                i = nxt[i];
                continue;
            }
            
            if(type == 1) vis[i ^ 1] = 1;
            int tp;
            if(type == 1){
                tp = i / 2  + 1;  
                if(i & 1) tp = -tp;
            }
            else tp = i + 1;
            
            int v = to[i];
            i = nxt[i];
            dfs(v);
            
            res[++ tot] = tp;
        }
    }
    
    int main()
    {
        scanf("%d%d%d",&type,&n,&m);
        cnt = 0;
        memset(head, -1, sizeof(head));
        for(int i = 1; i <= m; ++ i){
            int x, y; scanf("%d%d",&x,&y);
            add(x, y);
            if(type == 1) add(y, x);
            in[y] ++, out[x] ++;
        }
        
        if(type == 1){
            for(int i = 1; i <= n; ++ i)
                if((in[i] + out[i]) & 1){
                    printf("NO
    ");
                    return 0;
                }
        }
        else{
            for(int i = 1; i <= n; ++ i)
                if(in[i] != out[i]){
                    printf("NO
    ");
                    return 0;
                }
        }
        
        for(int i = 1; i <= n; ++ i){
            if(head[i] != -1){
                dfs(i); break;
            }
        }
        
        if(tot < m) printf("NO
    ");
        else{
            printf("YES
    ");
            for(int i = tot; i >= 1; -- i) printf("%d ",res[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    Apache Druid 的集群设计与工作流程
    跨越算法开篇
    十分钟了解Apache Druid(集数据仓库、时间序列、全文检索于一体的存储方案)
    时间序列数据库(TSDB)初识与选择(InfluxDB、OpenTSDB、Druid、Elasticsearch对比)
    C#多线程(6):线程通知
    C#多线程(5):资源池限制
    C#多线程(4):进程同步Mutex类
    C#多线程系列(3):原子操作
    C#多线程系列(2):多线程锁lock和Monitor
    C#多线程系列(1):Thread
  • 原文地址:https://www.cnblogs.com/A-sc/p/13752446.html
Copyright © 2020-2023  润新知