>1 樱子的爱好
题目
https://codeforces.com/contest/2008/problem/D
思路
以
5 4 1 3 2
10011
为例
i = 1, p1 = 5, s5 = 1--> i = 5, p5 = 2, s2 = 0 --> i = 2, p2 = 4, s4 = 1 --> i = 4, p4 = 3, s3 = 0 --> i = 3, p3 = 1, s1 = 1
无论i = 1还是5, 2, 4, 3,最终黑色的个数都一样,因为会重复这个过程,所以它们就在一根树枝上,可以把1看作根结点,后面的数字标记一下,表示已经操作过了,就能跳过,将它们的父亲都设为1, 最终遍历就直接输出父亲节点的黑色数量
代码
#include <iostream>
#include <vector>
#include <string>using namespace std;int main()
{int t;cin >> t;while (t--){int n;cin >> n;vector<int> p(n+1, 0), a(n+1, 0), goal(n+1, 0), cnt(n+1, 0), nu(n+1, 0);for (int i = 1; i <= n; i++) cin >> p[i], a[i] = p[i];string s;cin >> s;for (int i = 0; i < n; i++){if (s[i] == '0') nu[i + 1]++;}int count = 0;for (int i = 1; i <= n; i++){if (!goal[i]){int num = p[i];cnt[i] += nu[num];goal[num] = 1;count++;int res = p[num];p[num] = i;while (num != i){num = res;cnt[i] += nu[num];goal[num] = 1;count++;res = p[num];p[num] = i;}if (count == n) break;}}for (int i = 1; i <= n; i++) cout << cnt[p[a[i]]] << ' ';cout << endl;}
}
>2 小诚因为金铲铲D不到牌破产啦
题目
http://oj.whpu.tech:7788/problem/299
代码
#include <iostream>
#include <string>using namespace std;
const int N = 2e5 + 10;
int p[N], a[N], b[N];int findd(int x);
void uniona(int x, int y);
int main()
{int n, m; cin >> n >> m;for (int i = 1; i <= n; i++) cin >> a[i], p[i] = i;for (int i = 1; i <= n; i++) cin >> b[i];while (m--){int x, y; cin >> x >> y;int p1 = findd(x), p2 = findd(y);if (p1 != p2) uniona(p1, p2);}for (int i = 1; i <= n; i++){if (i == p[i]){if (a[i] != b[i]){cout << "No" << endl;return 0;}}}cout << "Yes" << endl;
}
int findd(int x)
{int a = x;while (a != p[a]) a = p[a];int b = x;while (b != a){int c = p[b];p[b] = a;b = c;}return a;
}
void uniona(int x, int y)
{p[x] = y;a[y] += a[x];b[y] += b[x];
}