CF1610F Mashtali: a Space Oddysey 做题记录

CF1610F Mashtali: a Space Oddysey

Description

给定一张含 \(n\) 个点 \(m\) 条边的无向图,结点编号为 \(1\)\(n\)

每条边有边权 \(w_i\),而 \(w_i\) 只能等于 \(1\)\(2\)。蓝想要给每条边定向,使得图尽可能的可爱。

图的可爱程度定义为图中好的结点的数量。一个结点 \(v\) 是好的,当且仅当令 \(d^+(v)\)\(v\) 所有出边的权值和,令 \(d^-(v)\)\(v\) 所有入边的权值和,有 \(|d^+(x)-d^-(x)|=1\)

试着帮蓝找到图的最大可能可爱程度,并且给出任意一种构造方案。

本题数据满足:\(1 \leq n,m \leq 3\times10^5,1 \leq u_i,v_i \leq n,\mathbf{w_i\in\{1,2\}}\)

Solution

先考虑问题的简化版:所有的 \(w_i=1\)

首先答案有一个上界:度数为奇数的点的个数。现在我们试图让答案达到这个上界。

建立超级源点 \(T\),如果点 \(v\) 的度数为奇数,则新建一条无向边 \((v,T)\)

现在所有节点的度数都是偶数。在新图上跑出一条欧拉回路,回路上经过这条边的方向就是答案中边的方向。

在欧拉回路中,每一个点都被进出相同次。对于一条边 \((v,T)\),如果经过的方向是 \(v \rightarrow T\),那么在原图中就对应 \(d^+(v)-d^-(v)=1\);反之则对应 \(d^-(v)-d^+(v)=1\)

再回到原问题。考虑将图拆为两部分,一部分只包含 \(w_i=1\) 的边,另一部分只包含 \(w_i=2\) 的边,对每一部分用上述方法跑欧拉回路。但我们只能让 \(|d^+(x)-d^-(x)|\) 为奇数的点最大化,无法保证 \(|d^+(x)-d^-(x)|=1\) 个数最大化。

问题出在两个部分不能完全独立。令 \(F(x),S(x)\) 分别表示 \(x\) 在第一、第二部分中对应的点,\(d1(x),d2(x)\) 分别表示 \(x\) 这个点在第一、第二部分中对应点的度数,我们在尝试构造一张新图:

  1. \(w(u,v)=1\),则建边 \((F(u),F(v))\)
  2. \(w(u,v)=2\),则建边 \((S(u),S(v))\)
  3. \(d1(x),d2(x)\) 均为奇数,则建边 \((F(x),S(x))\)
  4. 若只有 \(d1(x)\) 为奇数,则建边 \((T,F(x))\)
  5. 若只有 \(d2(x)\) 为奇数,则建边 \((T,S(x))\)

新图仍然满足所有节点的度数是偶数,但新图的欧拉回路就可以成为答案。

\(V(x)=d^+(x)-d^-(x)\)

对于一个满足条件 \(3\) 的节点,若欧拉回路中方向为 \(F(x) \rightarrow S(x)\),那么对应原图中 \(V(F(x))=1,V(S(x))=-2\),则有 \(V(x)=-1\)。反之则有 \(V(x)=1\)

对于一个满足条件 \(4\) 的节点,分析同上。对于一个满足条件 \(5\) 的节点,其一定不会成为好点。

那么我们的欧拉回路使得所有邻边权值和为奇数的点都成为了好点。

int n,m,T;
int head[N],tot,d1[N],d2[N],ans[N<<1];
bool vis[N],usd[N<<1];

#define F(x) x
#define S(x) x+n

struct Edge{
    int v,id,tp;
};
vector<Edge> e[N];

void Add(int u,int v,int w){
    e[u].push_back({v,w,1});
    e[v].push_back({u,w,2});
}

void dfs(int x){
    vis[x]=1;
    for(int i=head[x];i<(signed)e[x].size();i=head[x]){
        head[x]=i+1;
        if(usd[e[x][i].id]) continue;
        usd[e[x][i].id]=1;
        ans[e[x][i].id]=e[x][i].tp;
        dfs(e[x][i].v);
    }
}

signed main(){
    read(n),read(m);
    for(int i=1;i<=m;i++){
        int u,v,w;
        read(u),read(v),read(w);
        if(w==1){
            Add(F(u),F(v),i);
            d1[u]++,d1[v]++;
        }
        else{
            Add(S(u),S(v),i);
            d2[u]++,d2[v]++;
        }
    }
    int cnt=m,Ans=0; T=2*n+1;
    for(int i=1;i<=n;i++){
        if((d1[i]&1)&&(d2[i]&1)) Add(F(i),S(i),++cnt);
        else if(d1[i]&1) Add(T,F(i),++cnt);
        else if(d2[i]&1) Add(T,S(i),++cnt);
        int cd=d1[i]+d2[i]*2;
        if(cd&1) Ans++;
    }
    for(int i=1;i<=T;i++){
        if(!vis[i]){
            dfs(i);
        }
    }
    printf("%d\n",Ans);
    for(int i=1;i<=m;i++) putchar(ans[i]+'0');
    puts("");
    return 0;
}

posted @ 2025-01-24 21:20  XP3301_Pipi  阅读(14)  评论(0)    收藏  举报
Title