[TOC]c++
###codeforces 794D Labelling Cities 題目傳送門git
###題意 給出一個$n$個點$m$條邊的圖,要求給圖中的每個點賦一個值$x[i]$,使得任意兩個點之間有邊當且僅當$|x[i]-x[j]|<=1$。問是否存在知足條件的方案,若是有,輸出每一個點的值。$(2\leq n \leq 310^5,1 \leq m \leq 310^5)$spa
###題解 這個題目須要一些腦洞。總共須要想到兩個結論: 1.對於一些沒有邊直接相連的點,若是另外一個點鏈接了超過2個這些點,那麼確定就是無解的。 2.若是對於兩個點,他們相鄰的點(包括本身)所組成集合相同,若是題目有解,那麼必定會有一種合法方案中,這兩個點的值相同。 想到這兩個點差很少就能夠作出來了。第一個比較好證實,由於若是一個點鏈接了兩個以上互不相連的點,那麼這些點當中必定會有兩個點的$x$值差值小於等於1,而且之間沒有邊相連。這個畫畫圖理解一下就很容易的出來了。重點在於第二個,因爲這兩個點的相連的點都是相同的,那麼這兩個點和他們鏈接的那些點的差值都是相同的,因此咱們將這兩個點的值賦爲相同的也是合法的。因而咱們能夠藉助第二個結論,用哈希將全部值相同的點都縮在一塊兒,這樣剩下來的就是值不相同的點了。再根據第一個點,咱們能夠知道這個縮完點的圖必定是一條鏈了,而後咱們從鏈頂開始賦值就好了。code
###Codeget
#include <bits/stdc++.h> using namespace std; typedef long long ll; bool Finish_read; template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;} template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');} template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');} template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);} /*================Header Template==============*/ #define PAUSE printf("Press Enter key to continue..."); fgetc(stdin); const int M=3e5+500; int n,m,Base=13131; std::vector<int>G[M],F[M]; ll H[M]; int idx[M],fa[M],res[M]; typedef std::vector<int>::iterator vit; /*==================Define Area================*/ ll Hash(int x) { sort(G[x].begin(),G[x].end()); ll res=0; for(vit it=G[x].begin();it!=G[x].end();++it) { res=res*Base+*it; } return res; } bool cmp(int a,int b) {return H[a]<H[b];} int main() { read(n);read(m); for(int i=1;i<=n;i++) G[i].push_back(i); for(int i=1,u,v;i<=m;i++) { read(u);read(v); G[u].push_back(v); G[v].push_back(u); } for(int i=1;i<=n;i++) H[i]=Hash(i),idx[i]=i;; sort(idx+1,idx+1+n,cmp); for(int i=1;i<=n;i++) { int x=idx[i],y=idx[i-1]; fa[x]=(H[x]!=H[y])?x:fa[y]; } for(int i=1;i<=n;i++) { for(vit it=G[i].begin();it!=G[i].end();++it) { int j=*it; if(fa[i]!=fa[j]) F[fa[i]].push_back(fa[j]); } } int st; for(int i=1;i<=n;i++) { if(fa[i]!=i) continue ; sort(F[i].begin(),F[i].end()); F[i].erase(unique(F[i].begin(),F[i].end()),F[i].end()); if(F[i].size()>2) return puts("NO"),0; if(F[i].size()<=1) st=i; } queue<int>Q; Q.push(st); res[st]=1; while(!Q.empty()) { int o=Q.front();Q.pop(); for(vit it=F[o].begin();it!=F[o].end();++it) { if(!res[*it]) Q.push(*it),res[*it]=res[o]+1; } } puts("YES"); for(int i=1;i<=n;i++) { printf("%d ",res[fa[i]]); } puts(""); return 0; }