题目描述
一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会。
今年的面具都是主办方特别定制的。每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具。每个面具都有一个编号,主办方会把此编号告诉拿该面具的人。
为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的技术将每个面具的编号标在了面具上,只有戴第i 类面具的人才能看到戴第i+1 类面具的人的编号,戴第k 类面具的人能看到戴第1 类面具的人的编号。
参加舞会的人并不知道有多少类面具,但是栋栋对此却特别好奇,他想自己算出有多少类面具,于是他开始在人群中收集信息。
栋栋收集的信息都是戴第几号面具的人看到了第几号面具的编号。如戴第2号面具的人看到了第5 号面具的编号。栋栋自己也会看到一些编号,他也会根据自己的面具编号把信息补充进去。
由于并不是每个人都能记住自己所看到的全部编号,因此,栋栋收集的信 息不能保证其完整性。现在请你计算,按照栋栋目前得到的信息,至多和至少有多少类面具。由于主办方已经声明了k≥3,所以你必须将这条信息也考虑进去。
输入输出格式
输入格式:
第一行包含两个整数n, m,用一个空格分隔,n 表示主办方总共准备了多少个面具,m 表示栋栋收集了多少条信息。接下来m 行,每行为两个用空格分开的整数a, b,表示戴第a 号面具的人看到了第b 号面具的编号。相同的数对a, b 在输入文件中可能出现多次。
输出格式:
包含两个数,第一个数为最大可能的面具类数,第二个数为最小可能的面具类数。如果无法将所有的面具分为至少3 类,使得这些信息都满足,则认为栋栋收集的信息有错误,输出两个-1。
输入输出样例
说明
50%的数据,满足n ≤ 300, m ≤ 1000;
100%的数据,满足n ≤ 100000, m ≤ 1000000。
Solution
有思维难度而没有算法难度的奇奇怪怪的图论题==
分情况讨论八。
如果只有环的情况,明显就是所有环的长度取gcd是种类的最大值。如果又有环又有链,链实际上没用,只用判环就好。如果只有链,那么把所有链拼到一起,总长度就是种类数的最大值,最小值就是3-ans能被ans整除的最小值。
关于环,如果建出来的正图没有环,但是变成无向图是有环,如何去判断?就建反边,正边权为1,反边权为-1,正常跑dfs判环就可以叻。
【注意】环长度每次是取绝对值!!!(有可能是负的减正的)
还有一个有趣的事实:任何数和0取gcd结果都是它本身!!
Code
#include<bits/stdc++.h> using namespace std; int n, m; struct Node { int v, nex, w; Node(int v = 0, int nex = 0, int w = 0) : v(v), nex(nex), w(w) { } } Edge[2000005]; int h[100005], stot; void add(int u, int v, int d) { Edge[++stot] = Node(v, h[u], d); h[u] = stot; } int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } int vis[100005], dep[1000005], ans, len, lenmi, lenma; void dfs(int u, int deep) { if(!vis[u]) { vis[u] = 1; dep[u] = deep; lenmi = min(lenmi, deep); lenma = max(lenma, deep); for(int i = h[u]; i; i = Edge[i].nex) { int v = Edge[i].v; dfs(v, deep + Edge[i].w); } } else ans = gcd(ans, abs(deep - dep[u])); } int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= m; i ++) { int u, v; scanf("%d%d", &u, &v); add(u, v, 1); add(v, u, -1); } for(int i = 1; i <= n; i ++) if(!vis[i]) { dfs(i, 0); len += lenma - lenmi + 1; lenmi = lenma = 0; } if(ans >= 3) { for(int i = 3; i <= ans; i ++) if(ans % i == 0) { printf("%d %d", ans, i); break; } } else if(ans == 0 && len >= 3) printf("%d 3", len); else printf("-1 -1"); return 0; }