• 【学习笔记】[COCI2018-2019#1] Teoretičar


    首先,可以发现 C C C等于所有点度数的最大值,我们能用到的颜色数目为 2 x ≥ C 2^x\ge C 2xC

    考虑分治,将边集划分为 E = E 1 + E 2 E=E_1+E_2 E=E1+E2,使得 E 1 , E 2 E_1,E_2 E1,E2中点度数的最大值都不超过 2 x − 1 2^{x-1} 2x1。这样,我们将 [ 1 , 2 x − 1 ] [1,2^{x-1}] [1,2x1]中的颜色分配给 E 1 E_1 E1 [ 2 x − 1 + 1 , 2 x ] [2^{x-1}+1,2^x] [2x1+1,2x]中的颜色分配给 E 2 E_2 E2,就可以递归到子问题。显然当 C = 1 C=1 C=1时,可以将所有边染成同一个颜色。

    显然,我们可以用欧拉回路解决这个问题。但是这个做法常数比较大。考虑 CF1499G Graph Coloring 的做法,维护若干个环和若干条端点互不相同的链(因为是二分图,所以环的长度一定是偶数),这可以用带权并查集维护。注意并查集的维护对象是每条边,合并两条边的时候限制等价于这两条边所属集合不同。

    复杂度 O ( m log ⁡ m ) O(m\log m) O(mlogm)

    #include
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define inf 0x3f3f3f3f
    using namespace std;
    const int N=2e5+5;
    const int M=5e5+5;
    int L,R,m,U[M],V[M],du[N],st[N];
    int fa[M],val[M],tag[M],res[M];
    vector<int>v;
    int find(int x){
        if(fa[x]==x)return x;
        int tmp=fa[x];
        fa[x]=find(fa[x]);
        val[x]^=val[tmp];
        return fa[x];
    }
    void upd(int x){
        find(x);
        if(!(val[x]^tag[fa[x]])){
            tag[fa[x]]^=1;
        }
    }
    void unionset(int x,int y){
        int u=find(x),v=find(y);
        if(u!=v){
            val[u]=val[x]^val[y]^1,fa[u]=v;
        }
    }
    void solve(vector<int>&v,int cur){
        if(v.size()==0)return;
        for(auto e:v){
            fa[e]=e,val[e]=0,tag[e]=0,st[U[e]]=st[V[e]]=0;
        }
        int f=0;
        for(auto e:v){
            int x=U[e],y=V[e];
            if(st[x]||st[y])f=1;
            if(!st[x]&&!st[y]){
                st[x]=st[y]=e;
            }
            else if(!st[x]){
                upd(st[y]);
                unionset(e,st[y]);
                st[x]=e,st[y]=0;
            }
            else if(!st[y]){
                upd(st[x]);
                unionset(e,st[x]);
                st[y]=e,st[x]=0;
            }
            else{
                upd(st[x]),upd(st[y]);
                unionset(e,st[x]),unionset(e,st[y]);
                st[x]=st[y]=0;
            }
        }
        if(f==0){
            for(auto e:v)res[e]=1;
        }
        else{
            vector<int>vl,vr;
            for(auto e:v){
                find(e);
                if(val[e]^tag[fa[e]]){
                    vr.pb(e);
                }
                else{
                    vl.pb(e);
                }
            }
            solve(vl,cur>>1),solve(vr,cur>>1);
            for(auto e:vr)res[e]+=cur>>1;
        }
    }
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(0),cout.tie(0);
        cin>>L>>R>>m;
        for(int i=1;i<=m;i++){
            cin>>U[i]>>V[i],V[i]+=L;
            du[U[i]]++,du[V[i]]++,v.pb(i);
        }
        int dmax=0;
        for(int i=1;i<=L+R;i++)dmax=max(dmax,du[i]);
        int x=2;while(x<dmax)x<<=1;
        solve(v,x);
        cout<<x<<"\n";
        for(int i=1;i<=m;i++)cout<<res[i]<<"\n";
    }
    
    • 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
  • 相关阅读:
    Mysql 数据备份详解
    Netty 学习记录
    【Python计算机视觉】Python全栈体系(二十四)
    阵列信号处理——研究背景与现状
    InnoDB:一条update语句执行过程
    清空回收站的照片还能找回来吗?照片恢复用这招
    security加密解密
    DHCP动态主机配置协议
    ctfshow-web2(SQL注入)
    论文分享 | 利用单模态自监督学习实现多模态AVSR
  • 原文地址:https://blog.csdn.net/cqbzlydd/article/details/134254553