题解 P7816 「Stoi2032」以父之名
Konnyaku_LXZ · · 题解
考虑通过欧拉回路来构造答案。
我们建立一个虚点,向所有度数为奇数的点连权值为1的虚边,而度数为奇数的点必然有偶数个(考虑初始时所有点都是孤立的,度数均为
在跑欧拉回路时,假设我们通过边权为
为什么要这么选呢?因为对于每个点
总结一下,我们整道题的思路就是:建立一个虚点,向所有度数为奇数的点连权值为
最后吐槽一下,这题有亿点点卡常。
Code:
#include<bits/stdc++.h>
#define rg register
using namespace std;
const int MAXN=1e6+50,MAXM=1e7+50;
typedef long long LL;
int read(){int cnt=0;char c=getchar();while(c<'0'||c>'9') c=getchar();while(c>='0'&&c<='9'){cnt=(cnt<<1)+(cnt<<3)+(c^48);c=getchar();}return cnt;}
void write(int x){if(x==0) putchar('0');else putchar('1');}
struct edge{int nxt,to,val,ans;};
edge e[MAXM];//e[i].nxt为不区分权值的下一条边
int head[MAXN],Cnte=1;//head[i]表示与i相连的第一条边(不区分权值)
int nxt[MAXM],now[MAXN][3];//nxt[i]表示权值和当前边相同的下一条边(即区分权值),now[i][j]表示第一条与i相连的权值为j的边
int N,M,deg[MAXN];
void adde(int u,int v,int w){
++Cnte;
e[Cnte]=(edge){head[u],v,w,-1};
nxt[Cnte]=now[u][w];
now[u][w]=head[u]=Cnte;
}
void dfs(int u,int pre){
while(now[u][pre]&&e[now[u][pre]].ans!=-1) now[u][pre]=nxt[now[u][pre]];//优先选权值相同的边
if(!now[u][pre]){pre=(pre==1?2:1);while(now[u][pre]&&e[now[u][pre]].ans!=-1) now[u][pre]=nxt[now[u][pre]];}//后选择权值不同的边
if(!now[u][pre]) return;
e[now[u][pre]].ans=0;e[now[u][pre]^1].ans=1;
int t=now[u][pre];
now[u][pre]=nxt[now[u][pre]];
dfs(e[t].to,pre);
for(rg int i=head[u];i;i=e[i].nxt){
head[u]=e[i].nxt;
if(e[i].ans==-1){e[i].ans=0;e[i^1].ans=1;dfs(e[i].to,e[i].val);}
}
}
void Init(){
N=read();M=read();
for(rg int i=1;i<=M;++i){
int u=read(),v=read(),w=read();
adde(u,v,w);adde(v,u,w);
++deg[u];++deg[v];
}
}
void Solve(){
for(rg int i=1;i<=N;++i) if(deg[i]&1){adde(N+1,i,1);adde(i,N+1,1);}//度数为奇数的点向虚点连一条虚边
dfs(1,1);
}
void Print(){
for(rg int i=1;i<=M;++i) write(e[i<<1].ans);
}
int main()
{
Init();
Solve();
Print();
return 0;
}