20180520模拟赛T1——math

【问题描述】

小美有 n 个点 m 条边。

让你给每个点一个正整数编号。

每条边有两个属性,相连的两个点的编号的 GCD 和 LCM。

题目保证整张图连通。

让你构造出一个编号。

【输入格式】

从文件 math.in 中读入数据。

第一行两个正整数 n 和 m。

接下去m行每行 4 个正整数 xi,yi,gcdi,lcmi。

【输出格式】

输出到文件 math.out 中。

如果是有解:

第一行一行 YES。

第二行 n 个数字表示编号。

否则输出一行NO。

【样例】

【样例输入】

1 0

【样例输出】

YES 1

【样例输入】

2 1
1 2 1 3

【样例输出】

YES 1 3

【样例输入】

3 2
3 2 1 2
3 1 1 10

【样例输出】

YES 5 1 2

【样例输入】

2 1
1 2 3 7

【样例输出】

NO

【数据规模】

对于\(100\%\)的数据\(2\le n \le 100,n-1 \le m \le n*(n-1)/2,1\le gcdi, lcmi \le 10^6\)

题解

这题其实就是一道暴力题,是根据\([a, b] \times (a, b) = a\times b\)。已知\(a\times b\),暴力枚举\(a\),然后把整张图dfs一遍判断其正确性即可。

不得不说:大力出奇迹!

另外,记得开long long。

题目加强版:CF 60C

代码

#include <cctype>
#include <cstdio>
#include <cstring>

typedef long long LL;
#define int long long

#define dd c = getchar()
inline void read(int& x)
{
	x = 0;
	char dd;
	bool f = false;
	for(; !isdigit(c); dd)
		if(c == '-')
			x = -x;
	for(; isdigit(c); dd)
		x = (x<<1) + (x<<3) + (c^48);
	if(f) x = -x;
}
#undef dd

inline int gcd(int __n, int __m)
{
	while (__n)
	{
		int __t = __m % __n;
		__m = __n;
		__n = __t;
	}
	return __m;
}

const int maxn = 105;

int n, m;

int ans[maxn];

struct edge
{
	LL cheng;
	int t;
	int ne;
	int gcdd;
} e[maxn*maxn];

int first[maxn];
bool vis[maxn];

int mm;
inline void add_edge(int f, int t, LL cheng, int gcdd) 
{
	e[++mm].ne = first[f];
	e[mm].t = t;
	e[mm].cheng = cheng;
	e[mm].gcdd = gcdd;
	first[f] = mm;

	e[++mm].ne = first[t];
	e[mm].t = f;
	e[mm].cheng = cheng;
	e[mm].gcdd = gcdd;
	first[t] = mm;
}

inline bool dfs(int n, int last)//dfs检验答案正确性 
{
	vis[n] = true;
	for(int i = first[n]; i; i = e[i].ne)
	{
		int to = e[i].t;
		if(to == last) continue;
		if(vis[to])
		{
			if((ans[to]*ans[n] != e[i].cheng) || (gcd(ans[to], ans[n]) != e[i].gcdd))
				return false;
		}
		else
		{
			ans[to] = e[i].cheng / ans[n];
			if(gcd(ans[to], ans[n]) != e[i].gcdd)
				return false;
			if(!dfs(to, n))
				return false;
		}
	}
	return true;
}

inline void print()
{
	puts("YES");
	for(int i = 1; i <= n; ++i)
		printf("%lld ", ans[i]);
}

inline void search()
{
	vis[1] = true;
	if(!first[1])
	{
		puts("NO");
		return;
	}
	LL k = e[first[1]].cheng;
	for(int i = 1; i*i <= k; ++i)//暴力枚举所有可能情况 
		if(!(k%i))
		{
			ans[1] = i;
			memset(vis, 0, sizeof(vis));
			if(dfs(1, 0))
			{
				print();
				return;
			}
			ans[1] = k/i;
			memset(vis, 0, sizeof(vis));
			if(dfs(1, 0))
			{
				print();
				return;
			}
		}
	puts("NO");
}

signed main()
{
	freopen("math.in", "r", stdin);
	freopen("math.out", "w", stdout);
	scanf("%lld%lld", &n, &m);
	if(n == 1)
	{
		puts("YES\n1");
		return 0;
	}
	for(int i = 1; i <= m; ++i)
	{
		int f, t, gcdd, lcmm;
		read(f), read(t), read(gcdd), read(lcmm);
		add_edge(f, t, (LL)(gcdd*lcmm), gcdd);
	}
	search();
	return 0;
}
posted @ 2018-05-20 19:06  pfy_pfy  阅读(182)  评论(0编辑  收藏  举报