题目链接:点击打开链接
题意:给定一些点,每个点有一个值,相连的点之间有gcd和lcm两个信息。求这些点权值。
思路:相连的点可以看做一个联通分量,判断是否存在一种合法的情况,需保证每一个联通分量都合法。当分量中某一个点权值确定了,由于给定gcd和lcm这两个信息,因此整个联通分量就确定了。因此我们可以以某一点为该联通分量的起点,枚举该点可以取得的值,每一次进行一次dfs深搜即可。
AC代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <cstring>
#define LL long long
using namespace std;
const int maxn = 150;
struct node
{
int v,g,l;
node(int vv,int gg,int ll )
{
v=vv,g=gg,l=ll;
}
};
vector<node> a[maxn];
bool vis[maxn];
int ans[maxn];
bool dfs(int x)
{
if(vis[x]) return true;
vis[x] = 1;
for(int i=0; i<a[x].size(); i++)
{
node t = a[x][i];
if(t.l%ans[x]!=0) return false;
LL tmp = (t.g*1LL)*(t.l*1LL);
int k = tmp/ans[x];
if(__gcd(k,ans[x])!=t.g ) return false;
if(vis[t.v] && k!=ans[t.v]) return false;
ans[t.v] = k;
if(!dfs(t.v)) return false;
}
return true;
}
bool check(int x)
{
node t = a[x][0];
for(int i=t.g; i<=t.l; i+=t.g)
{
memset(vis,0,sizeof(vis));
ans[x] = i;
if(dfs(x)) return true;
}
return false;
}
int main()
{
int n,m,e1,e2,g,l;
memset(ans,0,sizeof(ans));
cin>>n>>m;
for(int i=0; i<m; i++)
{
cin>>e1>>e2>>g>>l;
a[e1].push_back(node(e2,g,l));
a[e2].push_back(node(e1,g,l));
}
for(int i=1; i<=n; i++)
{
if(ans[i] || a[i].size()==0) continue;
if(!check(i))
{
cout<<"NO\n";
return 0;
}
}
cout<<"YES\n";
for(int i=1; i<=n; i++)
{
if(ans[i]==0) cout<<1<<" ";
else cout<<ans[i]<<" ";
}
return 0;
}