数学
【问题描述】
小美有 n 个点 m 条边。
让你给每个点一个正整数编号。
每条边有两个属性,相连的两个点的编号的 GCD 和 LCM。
题目保证整张图连通。
让你构造出一个编号。
【输入格式】
从文件 math.in 中读入数据。
第一行两个正整数 n 和 m。
接下去m行每行 4 个正整数 xi,yi,gcdi,lcmi。
【输出格式】
输出到文件 math.out 中。
如果是有解:
第一行一行 YES。
第二行 n 个数字表示编号。
否则输出一行NO。
【样例输入】
1 0
【样例输出】
YES
【问题描述】
小美有 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; }