Description
给定M个二元组(A_i, B_i),求X_1, …, X_N满足:对于任意(A_i, B_i),有|X_{A_i} - X_{B_i}| = 1成立。
Input
第1行,2个整数N、M。
第2行到第M + 1行,2个整数A_i和B_i。
Output
第1行,1个字符串,"YES"表示有解,"NO"表示无解。
第2行,N个整数,X_1, X_2, …, X_N,无解则不输出。
要求|X_i| <= 1,000,000,000,任意一解均可。
Sample Input
输入1:
3 3
1 2
2 3
3 1
输入2:
6 5
1 2
2 3
3 4
4 1
5 6
Sample Output
输出1:
NO
输出2:
YES
0 1 0 1 -99 -100
Data Constraint
对于40%的数据,1 <= N <= 10。
对于100%的数据,1 <= N <= 10,000,0 <= M <= 100,000,1 <= A_i, B_i <= N。
//written by zzy
题目大意:
给你M个二元组(Ai, Bi),求个{Xn},使对于任意(Ai, Bi),有|X_Ai-X_Bi|=1
题解:
初看以为是数论,后来发现是图论。
把每个Xi看成一个点,一个二元组(Ai, Bi)看成条边
因为X_Ai与X_Bi只能差一,所以可以使他们只为0或1
dfs染色,如果当前点没染过就染上个点相反的色;
如果染过,则判断是否合法
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#define N 10005
#define M 100005
using namespace std;
int i,j,n,m,l,t;
int a[N];
int x[M*2],y[M*2],next[M*2],list[N];
bool _check;
bool b[N];
void add(int x)
{
l++;
next[l]=list[x];
list[x]=l;
}
void dfs(int dep,int p)
{
for (int t=list[p];t;t=next[t])
if (b[y[t]])
{
b[y[t]]=false;
a[y[t]]=(a[x[t]]+1)%2;
dfs(dep+1,y[t]);
} else
{
if ((a[x[t]]+a[y[t]])%2==0) {
_check=false; return;
}
}
}
int main()
{
freopen("perfect.in","r",stdin);
freopen("perfect.out","w",stdout);
scanf("%d%d",&n,&m);
for (i=1;i<=m;i++)
{
scanf("%d%d",&x[i*2-1],&y[i*2-1]);
add(x[i*2-1]);
x[i*2]=y[i*2-1]; y[i*2]=x[i*2-1];
add(x[i*2]);
}
for (i=1;i<=n;i++) a[i]=-1,b[i]=true;
_check=true;
for (i=1;i<=n;i++)
if (a[i]==-1)
{
a[i]=0; b[i]=false;
dfs(1,i);
}
if (_check==false) printf("NO");
else {
printf("YES\n");
for (i=1;i<=n;i++)
printf("%d ",a[i]);
}
}