題解 CF547D 【Mike and Fish】
阿新 • • 發佈:2020-09-08
考慮將每個點的橫縱座標看作點,將原先在座標系上的點看作邊,那麼題目的要求即為將新圖中的每條邊定向後,每個點的入度出度的差的絕對值不大於 \(1\)。
因為度數為奇數的點的個數一定為偶數,所以可以將度數為奇數的點兩兩配對,在兩點之間連一條邊。這樣每個點度數就都為偶數了,然後可以用歐拉回路來給每條邊定向。每條邊的方向就對應著原先在座標系上的點的顏色。
和 Points and Segments 很像。
#include<bits/stdc++.h> #define maxn 800010 #define d 200010 using namespace std; template<typename T> inline void read(T &x) { x=0;char c=getchar();bool flag=false; while(!isdigit(c)){if(c=='-')flag=true;c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();} if(flag)x=-x; } int n,tot,las; int p[maxn],deg[maxn],bel[maxn]; bool vis[maxn],tag[maxn],used[maxn]; struct edge { int to,nxt; }e[maxn]; int head[maxn],edge_cnt=1; void add(int from,int to) { e[++edge_cnt]={to,head[from]},head[from]=edge_cnt; } void dfs(int x) { tag[x]=true; for(int &i=head[x];i;i=e[i].nxt) { int y=e[i].to; if(vis[i]) continue; used[i]=vis[i]=vis[i^1]=true,dfs(y); } } int main() { read(n); for(int i=1;i<=n;++i) { int x,y; read(x),read(y),y+=d; add(x,y),bel[i]=edge_cnt^1,add(y,x); deg[x]++,deg[y]++,p[++tot]=x,p[++tot]=y; } sort(p+1,p+tot+1),tot=unique(p+1,p+tot+1)-p-1; for(int i=1;i<=tot;++i) { int x=p[i]; if(deg[x]&1) { if(las) add(las,x),add(x,las),las=0; else las=x; } } for(int i=1;i<=tot;++i) if(!tag[p[i]]) dfs(p[i]); for(int i=1;i<=n;++i) putchar(used[bel[i]]?'b':'r'); return 0; }