2018.5.19 T1

数学
【问题描述】
小美有 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 ≤ N ≤ 100, − 1 ≤ M ≤ N * (N − 1)/2,1 ≤

gcdi,lcmi ≤ 10^6

——————————————————————————————————————

x*y=gcd*lcm

也就你只要确定一个数字,就可以确定其他数字,然后你暴力枚举第一个数,遇到不符合的就退出

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
const int Maxm=10005,Maxn=105;
struct edge {
	int t,next,gc,lc;
}e[Maxm<<1];
int n,m,cnt,flg,mi=1e13+7; 
int head[Maxn],dis[Maxn];
void add(int u,int t,int gc,int lc) {
	e[++cnt].t=t;e[cnt].gc=gc;e[cnt].lc=lc;e[cnt].next=head[u];head[u]=cnt;
}
int gcd(int a,int b) {return !b?a:gcd(b,a%b);}
void dfs(int u) {
	for (int i=head[u];i && !flg;i=e[i].next) {
		int v=e[i].t,gc=e[i].gc,lc=e[i].lc;
		if (dis[v]) {
			if (dis[v]*dis[u]==lc*gc && gcd(dis[v],dis[u])==gc) continue;
			flg=1;
		}
		else {
			if (lc*gc%dis[u]) flg=1;
			dis[v]=lc*gc/dis[u];
			if (gcd(dis[v],dis[u])!=gc) flg=1;
			else dfs(v);
		}
	}
}
signed main() {
	freopen("math.in","r",stdin);
	freopen("math.out","w",stdout);
	scanf("%lld%lld",&n,&m);
	for (int i=1;i<=m;i++) {
		int a,b,c,d;
		scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
		add(a,b,c,d);add(b,a,c,d);
		if (a==1 || b==1) mi=min(mi,c*d);
	}
	for (int i=1;i<=mi;i++) {
		flg=0;
		memset(dis,0,sizeof dis);
		dis[1]=i;
		dfs(1);
		if (!flg) {
			puts("YES");
			for (int j=1;j<=n;j++)
				printf("%lld ",dis[j]);
			return 0;
		}
	}
	puts("NO");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41893580/article/details/80381784
t1