20180520模擬賽T1——math

【問題描述】

小美有 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;
}
相關文章
相關標籤/搜索