我采用了暴力搜索的办法, 当然要根据以下性质剪枝:
对任意两个整数x, y
x*y=gcd(x, y)*lcm(x, y)
利用这个剪枝, 如果所有的连通组件都能访问到就是有解了
代码中第一次DFS找出所有连通组件, 第二次则是尝试访问所有点
写出代码
..:
#include <bits/stdc++.h> using namespace std; struct edg { int n, g, l; edg(int _n, int _g, int _l) { n=_n, g=_g, l=_l; } }; struct cmp { int s, h; cmp(int _s, int _h) { s=_s, h=_h; } }; typedef vector<edg> ve; typedef vector<cmp> vc; #define pb push_back #define ret return int f, t; int w[501]; int v[501]; ve g[501]; vc c; inline int dfs1(int x) { v[x]=1; int r=1; for (edg e : g[x]) if (!v[e.n]) r+=dfs1(e.n); ret r; } inline int dfs2(int x, int c, int p) { v[x]=1; w[x]=c; int r=1; for (edg e : g[x]) if (e.n!=p) { int p=e.g*e.l; if (v[e.n]) { if (c*w[e.n]!=p || __gcd(c, w[e.n])!=e.g) ret 0; } else { if (p%c==0 && __gcd(c, p/c)==e.g) r+=dfs2(e.n, p/c, x); else ret 0; } } ret r; } class GCDLCMEasy { public: string possible(int n, vector <int> A, vector <int> B, vector <int> G, vector <int> L) { for (int i=0; i<A.size(); i++) { g[A[i]].pb(edg(B[i], G[i], L[i])); g[B[i]].pb(edg(A[i], G[i], L[i])); } for (int i=0; i<n; i++) if (!v[i]) c.pb(cmp(i, dfs1(i))); memset(v, 0, sizeof v); f=1; for ( ; f && t<c.size(); t++) if (!g[c[t].s].empty()) { f=0; edg& e=g[c[t].s][0]; int p=e.g*e.l; for (int i=1; i<=p; i++) if (p%i==0 && __gcd(i, p/i)==e.g) { w[c[t].s]=i; if (dfs2(c[t].s, i, -1)==c[t].h) { f=1; break; } else { memset(v, 0, sizeof v); } } } ret f ? "Solution exists" : "Solution does not exist"; } };
No comments :
Post a Comment