洛谷P1477 假面舞会

坑死了......

题意:给你个有向图,你需要把点分成k种,满足每条边都是分层的(从i种点连向i + 1种点,从k连向1)。

要确保每种点至少有一个。

求k的最大值,最小值。

n <= 1e5, m <= 1e6, k >= 3。

解:

首先可以发现,如果存在一个环,那么k一定是环长的约数。

然后我们把所有环长的gcd求出来就行了......

考虑这几种情况:

情况①:

这启示我们要拓扑排序或建反向边。鉴于这个图可能有环,我们建长度为-1的反向边。

情况②:

这个红色的环怎么办?

事实上只要别的两个环满足了,这个组合起来的环也能够被满足(意会一下)。

情况⑨:

这启示我们在无环/环长全部为0的时候进行特殊处理。

然后写代码的时候出了一堆错......50分暴力发现比正解还难打,不会写......

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 
 5 const int N = 100010, M = 1000010, INF = 0x3f3f3f3f;
 6 
 7 struct Edge {
 8     int nex, v, len;
 9 }edge[M << 1]; int top = 1;
10 
11 int e[N], m, n, vis[N], small, large, fd, g;
12 
13 int gcd(int a, int b) {
14     if(!b) {
15         return a;
16     }
17     return gcd(b, a % b);
18 }
19 
20 inline void add(int x, int y, int z) {
21     top++;
22     edge[top].nex = e[x];
23     edge[top].len = z;
24     edge[top].v = y;
25     e[x] = top;
26     return;
27 }
28 
29 void DFS(int x, int in_e) { // error : in_edge space
30     small = std::min(small, vis[x]);
31     large = std::max(large, vis[x]);
32     //printf("vis[%d] = %d 
", x, vis[x]);
33     for(int i = e[x]; i; i = edge[i].nex) {
34         if((i ^ 1) == in_e) {
35             continue;
36         }
37         int y = edge[i].v;
38         if(vis[y] == INF) {
39             vis[y] = edge[i].len + vis[x];
40             DFS(y, i);
41         }
42         else {
43             int cir = abs(edge[i].len + vis[x] - vis[y]); // error : abs(vis[x] - vis[y]) + 1
44             //printf(">_<  >>>  [%d]%d [%d]%d 
", x, vis[x], y, vis[y]);
45             //printf("cir = %d 
", cir);
46             g = gcd(g, cir);
47             fd = 1;
48         }
49     }
50     return;
51 }
52 
53 int main() {
54 
55     scanf("%d%d", &n, &m);
56     for(int i = 1, x, y; i <= m; i++) {
57         scanf("%d%d", &x, &y);
58         add(x, y, 1);
59         add(y, x, -1);
60     }
61     memset(vis, 0x3f, sizeof(vis));
62     int lenth = 0;
63     for(int i = 1; i <= n; i++) {
64         if(vis[i] == INF) {
65             large = small = 1;
66             vis[i] = 1;
67             DFS(i, 0);
68             lenth += large - small + 1;
69         }
70     }
71 
72     //printf("fd = %d 
", fd);
73 
74     if(!fd || !g) { // error : !g space
75         if(n <= 2 || lenth <= 2) { // error : lenth <= 2 space
76             printf("-1 -1");
77         }
78         else {
79             printf("%d 3", lenth);
80         }
81         return 0;
82     }
83     if(g < 3) {
84         printf("-1 -1");
85     }
86     else {
87         printf("%d ", g);
88         for(int i = 3; i <= g; i++) {
89             if(g % i == 0) {
90                 printf("%d", i);
91                 break;
92             }
93         }
94     }
95 
96     return 0;
97 }
AC代码

太毒瘤了......

原文地址:https://www.cnblogs.com/huyufeifei/p/10026779.html