小美有 n 個點 m 條邊。git
讓你給每一個點一個正整數編號。spa
每條邊有兩個屬性,相連的兩個點的編號的 GCD 和 LCM。code
題目保證整張圖連通。get
讓你構造出一個編號。string
從文件 math.in 中讀入數據。it
第一行兩個正整數 n 和 m。io
接下去m行每行 4 個正整數 xi,yi,gcdi,lcmi。ast
輸出到文件 math.out 中。class
若是是有解:gc
第一行一行 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; }