1 条题解
-
0
自动搬运
来自洛谷,原作者为

zifanwang
RP++搬运于
2025-08-24 23:04:10,当前版本为作者最后更新于2024-09-30 15:10:33,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
考虑对于一个解,将每对 中 的终点权值 , 的起点权值 ,那么最终每个点的权值一定是 。
考虑先将每条边的终点权值都 ,那么现在要做的就是选一些点将其起点和终点的权值都 ,使得最终每个点的权值为 ,于是边的方向就不重要了。
因为是一颗树,考虑随便取一个点位根,从叶子节点开始贪心选。每次如果当前考虑的点权值 ,就从它连到父亲的边中随便选出若干个使其权值减到 ,如果 则无解。记录下选出的边,最终和没选择的边匹配即可。
参考代码:
#include<bits/stdc++.h> #define mxn 300003 #define pb push_back #define rep(i,a,b) for(int i=a;i<=b;++i) #define rept(i,a,b) for(int i=a;i<b;++i) #define drep(i,a,b) for(int i=a;i>=b;--i) using namespace std; struct edge{ int x,y; }e[mxn]; int n,m,c[mxn]; int tot,hd[mxn],vr[mxn<<1],ed[mxn<<1],nx[mxn<<1]; bool v[mxn],b[mxn]; vector<int>s1[mxn],s2[mxn]; inline void add(int x,int y,int z){ vr[++tot]=y,ed[tot]=z,nx[tot]=hd[x],hd[x]=tot; } void dfs(int x,int fa){ v[x]=1; for(int i=hd[x],y;i;i=nx[i])if(!v[y=vr[i]]){ dfs(y,x); } if(c[x]<0||c[x]>2){ puts("No"); exit(0); } if(!c[x])return; if(!fa){ puts("No"); exit(0); } vector<int>s; for(int i=hd[x],y;i;i=nx[i])if(vr[i]==fa){ s.pb(ed[i]); } if(c[x]>s.size()){ puts("No"); exit(0); } rept(i,0,c[x]){ c[fa]--,b[s[i]]=1; } } inline void out(int x,int y){ cout<<e[x].x<<" "<<e[x].y<<" "<<e[y].x<<" "<<e[y].y<<'\n'; } signed main(){ scanf("%d%d",&n,&m); for(int i=1,x,y;i<=m;++i){ scanf("%d%d",&x,&y); e[i]={x,y},c[x]++; add(x,y,i),add(y,x,i); } rep(i,1,n)if(!v[i])dfs(i,0); rep(i,1,m){ if(b[i])s2[e[i].y].pb(i); else s1[e[i].x].pb(i); } puts("Yes"); rep(i,1,n){ rept(j,0,s1[i].size())out(s2[i][j],s1[i][j]); } return 0; }
- 1
信息
- ID
- 8976
- 时间
- 1000ms
- 内存
- 1024MiB
- 难度
- (无)
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者