jzoj 4822.完美标号

19 篇文章 0 订阅
3 篇文章 0 订阅
该博客探讨了一个图论问题,给定M个二元组(A_i, B_i),需要找到一组X_1, ..., X_N,使得对于所有二元组,|X_{A_i} - X_{B_i}| = 1。通过将每个X_i视为图中的节点,二元组转化为边,博主提出使用DFS染色的方法来判断是否存在满足条件的解。博客提供了样例输入和输出,并给出了数据约束。" 89091382,8345383,Unity光照模型详解:光源类型与BRDF计算,"['游戏开发', 'Unity3D', '光照模型', '实时渲染', '图形学']
摘要由CSDN通过智能技术生成

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]);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值