当前位置: 代码迷 >> 综合 >> Interesting Computer Game
  详细解决方案

Interesting Computer Game

热度:41   发布时间:2024-02-06 23:37:06.0

题意:给你两组数A[n],B[n],第i次操作可以从A[i],B[i]中选择一个数,问最多可以选择多少个不同的数。

多场比赛下来,感觉翻译是个大问题,虽然翻译对了也大概率不会做,但翻译错了根本就莫得机会,英语渣哭晕在厕所。(日常牢骚)

这题我一开始想的是贪心做,然后想想不行,选择一个数对后面的影响蛮大的,然后就没然后了233。题解说把这些数对(<Ai,Bi>)看成边的端点,去求连通块的个数,然后结果是数的种类-不带环的连通块数量,我想想好像确实是这样,有环的话至少可以选到一个节点,从该节点出发可以遍历整个图(图为有向图,出发节点出发时不算经过),那么在这个图内的点都可以取到,与之相反,如果该图没有环,因为是有向图,那么不存在一个点使其遍历所有点,最多可以遍历n-1(边数)个点。

好了,还有一些细节在代码里讲

#include<cstdio>
#include<algorithm>
#include<cstring>using namespace std;const int N = 2e5 + 10;int pre[N], vis[N], arr[N];struct node {int x;int y;
}date[N];void init(int n) {for (int i = 0; i <= n*2; i++) {pre[i] = i;vis[i] = 0;}
}int find(int x) {//并查集return (x == pre[x]) ? x : pre[x] = find(pre[x]);
}void solve(int x, int y) {//合并,判断是否有环int fx = find(x);int fy = find(y);if (fx == fy) {vis[fy] = 1;//标记环}else {pre[fx] = fy;vis[fy] |=  vis[fx];//如果其中一个点在一个有环有向图里,那么不在的那个点可以加入该有环有向图}
}int main() {int t;scanf("%d", &t);for (int Case = 1; Case <= t; Case++) {int n,ans;scanf("%d", &n);init(n+2);for (int i = 1; i <= n; i++) {scanf("%d %d", &date[i].x, &date[i].y);arr[i*2-1] = date[i].x;//x,y过大,需要离散化arr[i*2] = date[i].y;}sort(arr+1,arr+1+2*n);int max_size = unique(arr + 1, arr + 1 + 2 * n) - (arr + 1);//将不相同的数在数组前面出现一个,得到不相同的数的个数for (int i = 1; i <= n; i++) {int l = lower_bound(arr+1,arr+1+max_size,date[i].x) - (arr + 1)+1;//第一个大于等于date[i].x的数的位置int r = lower_bound(arr + 1, arr + 1 + max_size, date[i].y) - (arr + 1)+1;solve(l, r);}ans = max_size;for (int i = 1; i <= max_size; i++) {if (pre[i] == i && !vis[i]) {//找到无环图ans--;}}printf("Case #%d: %d\n", Case, ans);}
}
  相关解决方案