codeforces 794D Labelling Cities

[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;
}
相關文章
相關標籤/搜索