洛谷P1477 假面舞會

坑死了......ide

題意:給你個有向圖,你須要把點分紅k種,知足每條邊都是分層的(從i種點連向i + 1種點,從k連向1)。spa

要確保每種點至少有一個。code

求k的最大值,最小值。blog

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

解:ci

首先能夠發現,若是存在一個環,那麼k必定是環長的約數。string

而後咱們把全部環長的gcd求出來就好了......it

考慮這幾種狀況:io

狀況①:event

這啓示咱們要拓撲排序或建反向邊。鑑於這個圖可能有環,咱們建長度爲-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 \n", 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 \n", x, vis[x], y, vis[y]);
45             //printf("cir = %d \n", 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 \n", 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代碼

太毒瘤了......

相關文章
相關標籤/搜索