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\) 这个点在第一、第二部分中对应点的度数,我们在尝试构造一张新图:
- 若 \(w(u,v)=1\),则建边 \((F(u),F(v))\);
- 若 \(w(u,v)=2\),则建边 \((S(u),S(v))\);
- 若 \(d1(x),d2(x)\) 均为奇数,则建边 \((F(x),S(x))\);
- 若只有 \(d1(x)\) 为奇数,则建边 \((T,F(x))\);
- 若只有 \(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;
}

浙公网安备 33010602011771号