Farmer John’s cows are showing off their new dance mooves!
At first, all NN cows (2≤N≤1052≤N≤105) stand in a line with cow ii in the iith position in line. The sequence of dance mooves is given by KK (1≤K≤2⋅1051≤K≤2⋅105) pairs of positions (a1,b1),(a2,b2),…,(aK,bK)(a1,b1),(a2,b2),…,(aK,bK). In each minute i=1…Ki=1…K of the dance, the cows in positions aiai and bibi in line swap. The same KK swaps happen again in minutes K+1…2KK+1…2K, again in minutes 2K+1…3K2K+1…3K, and so on, continuing indefinitely in a cyclic fashion. In other words,
For each cow, please determine the number of unique positions in the line she will ever occupy.
The first line contains integers NN and KK. Each of the next KK lines contains (a1,b1)…(aK,bK)(a1,b1)…(aK,bK) (1≤ai<bi≤N1≤ai<bi≤N).
Print NN lines of output, where the iith line contains the number of unique positions that cow ii reaches.
5 4 1 3 1 2 2 3 2 4
4 4 3 4 1
Problem credits: Chris Zhang
[/hide]
(Analysis by Chris Zhang)
For the first two subtasks, we can just simulate. NKNK minutes will suffice because the sequence of positions of an individual cow will start repeating within that time.
Now, onto the full solution. After the first KK swaps, we compute where each cow ends up. If a cow started at the ii-th position, let its new position be pipi. Let’s also track the set sisi of all positions that cow ii reached during the KK swaps. This does not take too much memory because the sum of the sizes of all sets sisi is bounded by 2K+N2K+N (every swap, at most two cows move, thus adding at most two elements to the sets).
Let’s build a directed graph on the positions that shows how the cows move every KK swaps. We have NN directed edges from all ii to pipi (1≤i≤N)(1≤i≤N). This graph is a bunch of cycles because after KK swaps, there is exactly one cow in each position, so the outdegree and indegree of each node is one. Therefore, the graph is a bunch of disjoint cycles (as with Swapity Swapity Swap).
We claim that the answers for all cows in the same cycle are the same. Because everything repeats every KK swaps, if two cows have ever been in the same position after a multiple of KK swaps, they would visit the same positions eventually. After KK swaps, cow ii goes to position pipi, so the answers for cow ii and cow pipi are the same. This logic extends to every cow in the cycle (the answer for cow pipi is equal to cow ppippi and so on).
So, what exactly is the answer for some cycle? It’s the size of the union of all the sets sisi for each cow ii in the cycle. In other words, the answer is the number of unique positions in all the sets in the cycle. The complexity of this solution is O(N+K)O(N+K).
Chris’ code:
#include <bits/stdc++.h> using namespace std; int N,K; int A[200001],B[200001]; //input int P[100001]; //as described in analysis vector<int>S[100001]; //as described in analysis int from[100001]; //from[i] = where the cow in position i originated from int cnt[100001]; //array to keep track of uniquePos int uniquePos; //# of unique reachable positions //add in S_node void add(int node){ for (int x:S[node]){ if (cnt[x]==0) uniquePos++; cnt[x]++; } } //remove S_node void remove(int node){ for (int x:S[node]){ if (cnt[x]==1) uniquePos--; cnt[x]--; } } bool vis[100001]; queue<int>q; //stores all nodes in current cycle void dfs(int node){ vis[node]=true; add(node); q.push(node); if (!vis[P[node]]) dfs(P[node]); } int main(){ cin>>N>>K; for (int i=0;i<K;i++) cin>>A[i]>>B[i]; //initialize from and S for (int i=1;i<=N;i++){ from[i]=i; S[i].push_back(i); } //simulate the first K swaps, keeping track of where each position can reach for (int i=0;i<K;i++){ S[from[A[i]]].push_back(B[i]); S[from[B[i]]].push_back(A[i]); swap(from[A[i]],from[B[i]]); } //compute array P after first K swaps for (int i=1;i<=N;i++) P[from[i]]=i; int ans[100001]; //run a DFS on each cycle for (int i=1;i<=N;i++) if (!vis[i]){ dfs(i); int tempAns=uniquePos; //the answer //assign the answer for all nodes in the cycle, which we've stored in this queue while (!q.empty()){ remove(q.front()); ans[q.front()]=tempAns; q.pop(); } } for (int i=1;i<=N;i++) cout<<ans[i]<<endl; return 0; }
Danny Mittal's code:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; public class DanceMoovesSilver { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer tokenizer = new StringTokenizer(in.readLine()); int n = Integer.parseInt(tokenizer.nextToken()); int k = Integer.parseInt(tokenizer.nextToken()); int[] cows = new int[n + 1]; List<Integer>[] viewed = new List[n + 1]; for (int j = 1; j <= n; j++) { cows[j] = j; viewed[j] = new ArrayList<>(); viewed[j].add(j); } for (long t = 1; t <= k; t++) { tokenizer = new StringTokenizer(in.readLine()); int a = Integer.parseInt(tokenizer.nextToken()); int b = Integer.parseInt(tokenizer.nextToken()); int c = cows[a]; int d = cows[b]; cows[a] = d; cows[b] = c; viewed[cows[a]].add(a); viewed[cows[b]].add(b); } int[] answer = new int[n + 1]; for (int r = 1; r <= n; r++) { if (cows[r] != 0) { List<Integer> cycle = new ArrayList<>(); int j = r; while (cows[j] != 0) { cycle.add(j); j = cows[j]; cows[cycle.get(cycle.size() - 1)] = 0; } Set<Integer> viewedHere = new HashSet<>(); for (int cow : cycle) { viewedHere.addAll(viewed[cow]); } for (int cow : cycle) { answer[cow] = viewedHere.size(); } } } StringBuilder out = new StringBuilder(); for (int j = 1; j <= n; j++) { out.append(answer[j]).append('\n'); } System.out.print(out); } }
[/hide]
© 2025. All Rights Reserved. 沪ICP备2023009024号-1