#include #include #include #include #include #include #include #include #include struct djset { std::vector upper; std::vector id; int n; djset(int n_) { n=n_; upper.resize(n); id.resize(n); for (int i=0;i edges; }; void add_edge(vertex &a,vertex &b,int col,int cnt,int id) { if (cnt==0) return; edge ab; edge ba; ab.dst=b.id; ba.dst=a.id; ab.rev=b.edges.size(); ba.rev=a.edges.size(); ab.col=col; ba.col=col; ab.cnt=cnt; ba.cnt=cnt; ab.id=id; ba.id=id; a.edges.push_back(ab); b.edges.push_back(ba); } int max_deg(std::vector &vs){ int deg=0; for (vertex &v:vs) { int sum=0; for (edge &e:v.edges) sum+=e.cnt; deg=std::max(deg,sum); } return deg; } int bad_edge(std::vector &vs) { int ret=0; for (vertex &v:vs) for (edge &e:v.edges) if (e.id==-1) ++ret; return ret; } void divide_edge(std::vector &v0,std::vector &v1,int a,int b,edge &e) { add_edge(v0[a],v0[b],e.col,(e.cnt+1)/2,e.id); add_edge(v1[a],v1[b],e.col,e.cnt/2,e.id); } void divide(std::vector &vs,std::vector &v0,std::vector &v1) { assert(max_deg(vs)%2==0); std::vector> vis; for (int i=0;i<(int)vs.size();++i) { vis.push_back(std::vector(vs[i].edges.size(),false)); } for (int i=0;i<(int)vs.size();++i) { int cur=i; int parity=0; while (vs[i].next_edge!=(int)vs[i].edges.size()) { edge e=vs[cur].edges[vs[cur].next_edge]; if (vis[cur][vs[cur].next_edge]) { ++vs[cur].next_edge; continue; } if (e.cnt%2==0) { divide_edge(v0,v1,cur,e.dst,e); vis[e.dst][e.rev]=true; ++vs[cur].next_edge; } else { if (parity==0) divide_edge(v0,v1,cur,e.dst,e); else divide_edge(v1,v0,cur,e.dst,e); vis[e.dst][e.rev]=true; ++vs[cur].next_edge; cur=e.dst; parity^=1; } } } } std::vector find_matching(std::vector vs) { int n=(int)vs.size(),m=0,M=1; for (vertex v:vs) m+=v.edges.size(); while (M1) { std::vector v0(n); std::vector v1(n); for (int i=0;i matching; for (vertex &v:vs) for (edge &e:v.edges) { if (v.id &vs,std::vector delete_edges) { std::vector ret(vs.size()); for (int i=0;i<(int)ret.size();++i) ret[i].id=i; std::set s; for (int &id:delete_edges) s.insert(id); for (vertex &v:vs) for (edge &e:v.edges) { if (v.id>e.dst) continue; if (s.count(e.id)!=0) { --e.cnt; s.erase(e.id); } add_edge(ret[v.id],ret[e.dst],e.col,e.cnt,e.id); } vs=ret; } std::vector> colorize2(std::vector &vs,int offset=0) { int D=max_deg(vs); if (D==1) { std::vector> ret; for (vertex &v:vs) for (edge &e:v.edges) { if (v.id>e.dst) continue; ret.push_back(std::make_pair(e.id,offset)); } return ret; } std::vector v0(vs.size()); std::vector v1(vs.size()); for (int i=0;i<(int)vs.size();++i) { v0[i].id=i; v1[i].id=i; } divide(vs,v0,v1); std::vector> ans0=colorize2(v0,offset); std::vector> ans1=colorize2(v1,offset+D/2); for (std::pair &p:ans0) { ans1.push_back(p); } return ans1; } std::vector> colorize(std::vector vs,int offset=0) { int D=max_deg(vs); if (D==0) return std::vector>(); else if (D==1) { std::vector> ans; for (vertex &v:vs) { for (edge &e:v.edges) { ans.push_back(std::make_pair(e.id,offset)); } } return ans; } else if (D%2==0) { int D2=1; while (D2 v0(vs.size()); std::vector v1(vs.size()); for (int i=0;i<(int)vs.size();++i) { v0[i].id=i; v1[i].id=i; } divide(vs,v0,v1); std::vector> ans0=colorize(v0,offset); std::set invalid; for (auto &p:ans0) { assert(p.second=(int)(D/2-(D2-D/2))) { invalid.insert(p.first); } } for (vertex &v:v0) { for (edge &e:v.edges) { if (v.id>e.dst) continue; if (invalid.count(e.id)) { add_edge(v1[v.id],v1[e.dst],-1,1,e.id); } } } std::vector> ans1=colorize2(v1,offset+(D/2-(D2-D/2))); for (std::pair &p:ans0) { if (invalid.count(p.first)==0) ans1.push_back(p); } return ans1; } else { std::vector matching=find_matching(vs); std::vector> ans0; std::vector> ans1; for (int &id:matching) { ans0.push_back(std::make_pair(id,offset)); } delete_edges(vs,matching); ans1=colorize(vs,offset+1); for (std::pair &p:ans1) { ans0.push_back(p); } return ans0; } } void contract(std::vector °,djset &ds,int D) { std::priority_queue> pq; for (int i=0;i<(int)deg.size();++i) { pq.push(std::make_pair(-deg[i],i)); } while (pq.size()>1) { std::pair a=pq.top();pq.pop(); std::pair b=pq.top();pq.pop(); if (-(a.first+b.first)>D) break; a.first+=b.first; ds.unite(a.second,b.second); pq.push(a); } ds.build_id(); } std::vector solve(int L,int R,int M,std::vector &a,std::vector &b) { int D=0; std::vector deg[2]; deg[0]=std::vector(L); deg[1]=std::vector(R); for (int i=0;i vs(2*sz); for (int i=0;i<(int)vs.size();++i) vs[i].id=i; for (int i=0;i> ps=colorize(vs); std::vector ans(M); for (auto &pair:ps) { if (pair.first &a,std::vector &b) { std::vector deg[2]; deg[0]=std::vector(L,0); deg[1]=std::vector(R,0); int nL=L,nR=R; for (int i=0;id) { --deg[0][a[i]]; if (L==nL || deg[0][nL-1]==d) { deg[0].push_back(0); ++nL; } a[i]=nL-1; ++deg[0][nL-1]; } if (deg[1][b[i]]>d) { --deg[1][b[i]]; if (R==nR || deg[1][nR-1]==d) { deg[1].push_back(0); ++nR; } b[i]=nR-1; ++deg[1][nR-1]; } } L=nL; R=nR; return; } std::mt19937 mt; void gen() { int L=100000; int R=100000; int M=100000; std::vector a(M); std::vector b(M); for (int i=0;i ans=solve(L,R,M,a,b); std::vector g(L+R); for (int i=0;i<(int)g.size();++i) g[i].id=i; for (int i=0;i cols; for (edge &e:v.edges) { cols.insert(e.col); } } std::cout<<"ok"< a(M); std::vector b(M); for (int i=0;i>a[i]>>b[i]; } transform(L,R,M,a,b); std::vector ans=solve(L,R,M,a,b); int D=0; for (int &c:ans) D=std::max(D,c+1); printf("%d\n",D); for (int &c:ans) { printf("%d\n",c); } } int main() { solve(); }