URAL1040

来源:互联网 发布:淘宝关键词竞争力公式 编辑:程序博客网 时间:2024/06/11 20:42

300人委员会的复仇

题目链接

分类dfs and simiar math

1.题意概述

  • 给你n个点和m条边构成的图,要你对着m条边进行赋值(为1到m的不重复分配),使得任意点的所有边的gcd的值为1,如果存在方案输出YES和分配方案,否则输出NO

2.解题思路

  • 我们考虑去按dfs序去编号,这样可以保证的是,某个点的边被访问,那么相邻的边至少有一条编号是连续的,但是隐隐感觉还缺少点啥?对!我们考虑根节点与它儿子编号不连续的情况,但是我们是从根节点开始dfs,对根节点编号为1,那么它和它儿子的gcd就一定为1,是不是很奇妙?

3.AC代码

struct Edge {    int to, val, next;} E[maxn << 1];int head[N], vis[N], cnt, gg, Gcd[maxn];void init() {    memset(head, -1, sizeof head);    memset(vis, 0, sizeof vis);    memset(Gcd, 0, sizeof Gcd);    cnt = 0; gg = 1;}void addedge(int u, int v, int w) {    E[cnt].to = v;    E[cnt].val = w;    E[cnt].next = head[u];    head[u] = cnt++;}void dfs(int u) {    vis[u] = 1;    for (int i = head[u]; ~i; i = E[i].next) {        int v = E[i].to;        int id = E[i].val;        if (!Gcd[id]) {            Gcd[id] = gg++;            if (!vis[v]) dfs(v);        }    }}int main() {    int n, m;    init();    scanf("%d%d", &n, &m);    rep(i, 1, m + 1) {        int u, v;        scanf("%d%d", &u, &v);        addedge(u, v, i);        addedge(v, u, i);    }    bool flag = 1;    dfs(1);//  rep(i, 1, m + 1) printf("%d ", Gcd[i]);//  puts("");    rep(u, 1, n + 1) {        int g = 0, len = 0;        for (int i = head[u]; ~i; i = E[i].next) {            len++;            int id = E[i].val;            if (!g) g = Gcd[id];            else g = __gcd(g, Gcd[id]);        }        if (len > 1 && g != 1) {            flag = 0;            break;        }    }    if (flag) {        puts("YES");        rep(i, 1, m + 1)        if (i == m)            printf("%d\n", Gcd[i]);        else printf("%d ", Gcd[i]);    } else puts("NO");    return 0;}