1. 程式人生 > >洛谷P1477 假面舞會

洛谷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 \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程式碼

太毒瘤了......