• 【学习笔记】CF1610F Mashtali: a Space Oddysey


    感觉智商还是不太够😅

    正常人的做法:答案上界是显然的,就是 ∑ w \sum w w为奇数的点的个数,因为限制很松。但是直接构造比较棘手,考虑两条边 ( x , v ) (x,v) (x,v) ( v , y ) (v,y) (v,y),如果这两条边的权值也相同,那么可以在原图中将 ( x , v ) (x,v) (x,v) ( v , y ) (v,y) (v,y)删掉,然后加入 ( x , y ) (x,y) (x,y)这条边。这样每次操作后,边的数目会减少 1 1 1。一直这样操作下去,最后每个点的度数不会超过 2 2 2,因此是若干环和链,显然从链的端点或者环上任意一点开始定向即可。

    具体实现方式是:枚举 x x x以及出边 v v v,然后再找到 v v v的一条出边 y y y,将 ( x , v ) (x,v) (x,v) ( v , y ) (v,y) (v,y)删掉,加入边 ( x , y ) (x,y) (x,y),然后 v v v赋值成 y y y,继续寻找 y y y的出边。写代码的时候要先把 ( x , v ) (x,v) (x,v)这条边删掉,直到 x x x的所有出边都扩展完了过后再加回来。最后还原方案只需建立二叉树然后从根节点开始遍历即可(和 kruskal \text{kruskal} kruskal重构树比较类似)。

    复杂度 O ( n + m ) O(n+m) O(n+m)。但是比较难写,估计要调半天。

    聪明人的做法:考虑欧拉回路。本质上就是利用了回路上出边和入边数目相同来构造,但是这道题的建图方式比较难。

    考虑建立 2 n + 1 2n+1 2n+1个点(因为 1 1 1 2 2 2其实本质上是对称的,所以把点复制一遍),建边方式如下:

    1.1 1.1 1.1 对于边权为 1 1 1的边 ( u , v ) (u,v) (u,v),加入边 ( u , v ) (u,v) (u,v)
    1.2 1.2 1.2 对于边权为 2 2 2的边 ( u , v ) (u,v) (u,v),加入边 ( u + n , v + n ) (u+n,v+n) (u+n,v+n)
    1.3 1.3 1.3 d i ( j ) d_i(j) di(j)表示 j j j连了多少条度为 i i i的边,如果 d 1 ( u ) d_1(u) d1(u) d 2 ( u ) d_2(u) d2(u)都为奇数,加入边 ( u , u + n ) (u,u+n) (u,u+n);如果只有 d 1 ( u ) d_1(u) d1(u)为奇数,加入边 ( u , 2 n + 1 ) (u,2n+1) (u,2n+1);如果只有 d 2 ( u ) d_2(u) d2(u)为奇数,加入边 ( u + n , 2 n + 1 ) (u+n,2n+1) (u+n,2n+1)

    跑欧拉回路,然后根据前两类边的方向就可以确定原图中边的方向。

    代码很简单。但是确实比较难想到😅

    我是小丑,所以写了第一种做法。

    #include
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    const int N=6e5+5;
    int n,m,ok[N],vs[N],vs2[N],U[N],V[N],W[N],du[N],du2[N],cnt,tot;
    pair<int,int>ans[N];
    vector<int>s[N][2];
    vector<int>vec;
    vector<int>G[N];
    vector<int>G2[N];
    int get(int x,int y){
        if(y==U[x])return V[x];
        return U[x];
    }
    void dfs(int i,int pre,int j){
        while(s[i][j].size()&&vs[s[i][j].back()]){
            s[i][j].pop_back();
        }if(s[i][j].size()==0){
            vec.pb(pre);
            return;
        }int t=s[i][j].back();
        vs[t]=1,s[i][j].pop_back();
        cnt++,U[cnt]=get(pre,i),V[cnt]=get(t,i),vs[cnt]=1;
        G[cnt].pb(t),G[cnt].pb(pre),du2[t]++,du2[pre]++;
        dfs(V[cnt],cnt,j);
    }
    void dfs2(int u){
        while(G2[u].size()&&vs2[G2[u].back()])G2[u].pop_back();
        if(G2[u].size()==0)return;
        int t=G2[u].back();G2[u].pop_back();
        vs2[t]=1,ans[t]={u,get(t,u)},dfs2(get(t,u));
    }
    void dfs3(int u){
        if(G[u].size()){
            int l=G[u][0],r=G[u][1];
            if(V[l]==U[r]){
                ans[l]={U[l],V[l]},ans[r]={U[r],V[r]};
            }
            else if(U[l]==U[r]){
                ans[l]={V[l],U[l]},ans[r]={U[r],V[r]};
            }
            else if(V[l]==V[r]){
                ans[l]={U[l],V[l]},ans[r]={V[r],U[r]};
            }
            else{
                ans[l]={V[l],U[l]},ans[r]={V[r],U[r]};
            }if(ans[l].fi!=ans[u].fi){
                swap(ans[l].fi,ans[l].se);
                swap(ans[r].fi,ans[r].se);
            }
            dfs3(l),dfs3(r);
        }
    }
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(0),cout.tie(0);
        cin>>n>>m,cnt=m;
        for(int i=1;i<=m;i++){
            int u,v,w;cin>>u>>v>>w,w--;
            s[u][w].pb(i),s[v][w].pb(i);
            if(w==0)ok[u]^=1,ok[v]^=1;
            U[i]=u,V[i]=v,W[i]=w;
        }
        for(int i=1;i<=n;i++){
            for(int j=0;j<2;j++){
                while(1){
                    while(s[i][j].size()&&vs[s[i][j].back()])s[i][j].pop_back();
                    if(s[i][j].size()==0)break;
                    int t=s[i][j].back();s[i][j].pop_back();
                    vs[t]=1,dfs(get(t,i),t,j);
                }while(vec.size()){
                    int t=vec.back();vec.pop_back();
                    vs[t]=0,s[U[t]][j].pb(t),s[V[t]][j].pb(t);
                }
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=0;j<2;j++){
                while(1){
                    while(s[i][j].size()&&vs[s[i][j].back()])s[i][j].pop_back();
                    if(s[i][j].size()==0)break;
                    int t=s[i][j].back();s[i][j].pop_back();
                    vs[t]=1;int k=get(t,i);
                    du[i]++,du[k]++,G2[i].pb(t),G2[k].pb(t);
                }
            }
        }
        for(int i=1;i<=n;i++)if(du[i]==1)dfs2(i);
        for(int i=1;i<=n;i++)dfs2(i);
        for(int i=1;i<=cnt;i++)if(du2[i]==0)dfs3(i);
        for(int i=1;i<=n;i++)tot+=ok[i];
        cout<<tot<<"\n";
        for(int i=1;i<=m;i++){
            if(ans[i].fi==U[i])cout<<1;
            else cout<<2;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
  • 相关阅读:
    分布式--OpenResty+lua+Redis实现限流与防爬虫
    设备远程运维的策略与实践
    JavaSE面试题05:类初始化和实例初始化
    使用PAM保障开发运营安全
    Orchestrator 对 MGR MySQL Group Replication的支持
    吴恩达deeplearning.ai:Tensorflow训练一个神经网络
    Qt实战案例(54)——利用QPixmap设计图片透明度
    SecureCRT (Mac/Windows)中文---远程连接与管理的安全新选择
    DeepMCP网络详解
    如何快速落地LLM应用?通过Langchain接入千帆SDK
  • 原文地址:https://blog.csdn.net/cqbzlydd/article/details/133622367