Topic Link: Click to open the link
The main idea: to give a graph, there are n points, N, if you want to divide the graph into the same number of K parts, require each of the internal can be linked to each other, then there will be a few k meet the conditions.
1, there is a theorem, if a tree to be divided into K nodes of a sub-tree, then there are n/k nodes corresponding to the number of nodes of the subtree is a multiple of K.
According to the above theorem, then we can calculate whether a tree can be divided into n/k, the topic given is a tree + an edge, so the end should be a ring and the node as the root of the subtree, if the ring to eliminate an edge, then become a tree, you can use the theorem to judge.
First find the node on the ring, and the size of the subtree at the root of the node. The number of nodes in a subtree will not become available directly. However, the number of nodes in the ring will change with the deleted edges, so to enumerate the deleted edges, find the node number is a multiple of k nodes, if it is n/k, then the proof k is possible.
#include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <algorithm >using namespace std; #pragma comment (linker, "/stack:102400000,102400000"); #define MAXN 100000+10struct node{int v , Next;} EDGE[MAXN<<1]; int HEAD[MAXN], h_cnt; int VIS[MAXN]; int A[MAXN], c[maxn], n; int s[maxn], m; int DP[MAXN]; int CNT[MAXN], SUM[MAXN]; void Add (int u,int v) {edge[h_cnt].v = v; Edge[h_cnt].next = Head[u]; Head[u] = h_cnt++;} int f (int x) {return c[x] = = x X:c[x] = f (c[x]);} int find1 (int x,int y) {if (f (x) = = f (y)) return 1; c[f (x)] = f (y); return 0;} void Dfs (int u) {dp[u] = 1; int I, V; for (i = head[u]; I! =-1; i = edge[i].next) {v = edge[i].v; if (Vis[v]) continue; DFS (v); Dp[u] + = Dp[v]; } return; int solve (int k) {int i, max1, temp = 0; memset (cnt,0,sizeof (CNT)); for (i = 1; I <= n; i++) {if (vis[i]) continue; if (dp[i]%k = = 0) temp++; } Sum[0] = 0; for (i = 1; i<= m; i++) {Sum[i] = (Sum[i-1] + dp[S[i]])%k; cnt[Sum[i]]++; } MAX1 = cnt[sum[m]] + temp; for (i = 1; i < m; i++) {cnt[sum[i]]--; cnt[(Sum[m]+sum[i])%k]++; MAX1 = Max (max1,cnt[(sum[m]+sum[i))%k]+temp); } if (max1 = = n/k) return 1; return 0;} int main () {int I, j, X, K, ans; Freopen ("1003.in", "R", stdin); Freopen ("1111.out", "w", stdout); while (scanf ("%d", &n)! = EOF) {memset (head,-1,sizeof (head)); h_cnt = 0; memset (vis,0,sizeof (VIS)); for (i = 1; I <= n; i++) {scanf ("%d", &a[i]); Add (a[i],i); C[i] = i; } for (i = 1; I <= n; i++) {if (Find1 (I,a[i])) break; } m = 0; s[++m] = i; Vis[i] = 1; x = A[i]; while (x = s[1]) {s[++m] = x; VIS[X] = 1; x = A[x]; } for (i = 1; I <= m; i++) DFS (s[i]); Ans = 0; for (k = 1; k <= N; k++) {if (n%k) continue; Ans + = solve (k); } printf ("%d\n", ans); } return 0;} /*127 9 12 2 3 4 8 6 10 5 8 1*/
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
hdu5329 (2015 + school 4)--question for the Leader