CF1423N

先将无向图转为一个 DAG,直接从大点向小点连边就可以。

考虑增量构造,假设当前已经构造完了集合 1,2,,i1,他们满足有边的点权值不同。现在我们加入第 i 个点。那么枚举他的出边,将出点按点权分为两类。如果我们最初令所有边权都为 1,那么当前点的出边边权也都为 1,所以出点点权为 0 可以通过将点权 +1,边权 1 的方式使得 i 号点的点权减 1,同时这个点原本的权值不变。同理点权为 0 的出点可以使 i 号点的点权 +1 。于是可以得到 degi+1 种不同的点权,根据抽屉原理可得一定有一个点权和出点都不同。

复杂度 O(n+k)

Copy
#include<bits/stdc++.h> #define N 2001001 #define MAX 5005 #define inf 1e18 using namespace std; typedef long long ll; typedef long double db; inline void read(ll &ret) { ret=0;char c=getchar();bool pd=false; while(!isdigit(c)){pd|=c=='-';c=getchar();} while(isdigit(c)){ret=(ret<<1)+(ret<<3)+(c&15);c=getchar();} ret=pd?-ret:ret; return; } ll n,k,x,y,val[N],cv[N],ce[N],fr[N],ed[N]; bool vis[N]; vector<pair<ll,ll> >v[N]; signed main() { read(n); read(k); for(int i=1;i<=k;i++) { read(x); read(y); fr[i]=x,ed[i]=y; val[x]++,val[y]++; ce[i]=1; if(x<y) v[y].push_back(make_pair(x,i)); else v[x].push_back(make_pair(y,i)); } for(int i=1;i<=n;i++) { ll cnt0=0,cnt1=0; for(auto j:v[i]) { ll x=j.first; if(cv[x]==0) cnt0++; else cnt1++; vis[val[x]]=true; } for(int j=val[i]-cnt0;j<=val[i]+cnt1;j++) { if(!vis[j]) { if(j<val[i]) { ll now=val[i]-j; for(auto t:v[i]) { if(cv[t.first]==0&&now) now--,ce[t.second]=0,cv[t.first]=1; } } else { ll now=j-val[i]; for(auto t:v[i]) { if(cv[t.first]==1&&now) now--,ce[t.second]=2,cv[t.first]=0; } } val[i]=j; break; } } for(auto j:v[i]) { ll x=j.first; vis[val[x]]=false; } } ll ans=0; for(int i=1;i<=n;i++) ans+=cv[i]; printf("%lld\n",ans); for(int i=1;i<=n;i++) if(cv[i]) printf("%d ",i); if(ans) puts(""); for(int i=1;i<=k;i++) printf("%lld %lld %lld\n",fr[i],ed[i],ce[i]); exit(0); }
posted @   CelticOIer  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示