Interesting Computer Game

链接:https://ac.nowcoder.com/acm/contest/5673/I
来源:牛客网

题目描述
Apollo is playing an interesting computer game. There are N N N rounds in the game.
At each round, the computer will give Apollo two integers ( a i a_i ai and b i b_i bi), and Apollo can do exactly one of the following three actions.
Apollo can do nothing.
If integer a i a_i ai has not been selected in all previous rounds, Apollo can select integer a i a_i ai.
If integer b i b_i bi has not been selected in all previous rounds, Apollo can select integer b i b_i bi.
Apollo has cracked the game, and he has known all the candidate numbers of each round before the game starts. Now he wants to know the maximum number of integers he can select with the optimal strategy.
I believe it would be very simple question for you, please help Apollo solve this question.
输入描述:
The first line is an integer T \mathbf{T} T ( 1 ≤ T ≤ 10 1 \leq \mathbf{T} \leq 10 1T10), which is the number of test cases.

Each test case begins with a line containing a positive integer N N N ( 1 ≤ N ≤ 1 0 5 1 \le N \le 10^5 1N105), indicating the number of rounds in this game.

Then N N N lines follow. The i i i-th line contains two integers a i a_i ai and b i b_i bi ( 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^9 1ai109, 1 ≤ b i ≤ 1 0 9 1 \le b_i \le 10^9 1bi109), indicating that two integers of the i i i-th round.
输出描述:
For each test case, output one line containing Case #x: y' , where x x x is the test case number and y y y is the answer.
示例1

输入
2
6
1 2
2 3
3 4
1 4
1 3
2 4
5
1 2
1 2
1 3
2 3
5 6
输出
Case #1: 4
Case #2: 4

首先,根据贪心原则,如果一个数只出现过一次,那么选这个数的结果一定不会变差。因为选这个只出现过一次的数会使总数加 1 1 1并且至多会使 1 1 1个数在之后不能被选择,也就是对应位置的另一个数且这个数在之前没被选过,在该位置之后不会再出现。但是如果选择这个不能被选的数情况和选只出现过一次的数一样,而什么都不选情况只会变差。
然后,如果序列里面所有的数都出现了至少两次,那么总存在一种选择方式使得每种数都能被选到。因为不可能通过选择一个数使得另一个数不能被选到。
以上策略可以通过拓扑排序实现,即先选只出现一次的,如果选择一个数导致另一个数只能被选一次,那么把另一个数入队。最后剩下的数都是出现多次的,在答案的基础上加上剩下的数的数量即可。

#include<bits/stdc++.h>

#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define sc(a) scahf("%c",&a);
#define ss(a) scanf("%s",a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%lld\n",a)
#define pc(a) putchar(a)
#define ms(a) memset(a,0,sizeof(a))
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define repd(i, a, b) for(register int i=a;i>=b;--i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
#define ll long long
#define ull unsigned long long
#define vi vector<int>
#define pii pair<int,int>
#define mii unordered_map<int,int>
#define msi unordered_map<string,int>
#define lowbit(x) ((x)&(-(x)))
#define ce(i, r) i==r?'\n':' '
#define pb push_back
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define INF 0x3f3f3f3f
#define pr(x) cout<<#x<<": "<<x<<endl
using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 1e5 + 10;
vi seq;
int a[N], b[N], cnt[N << 1], n, T;
mii num;
queue<int> q;
set<int> st[N << 1];

int main() {
    T = qr();
    int cse = 0;
    while (T--) {
        n = qr();
        seq.clear(), num.clear();
        repi(i, 1, 2 * n)st[i].clear(), cnt[i] = 0;
        while (!q.empty())q.pop();
        repi(i, 1, n)a[i] = qr(), b[i] = qr(), seq.pb(a[i]), seq.pb(b[i]);
        sort(all(seq));
        seq.erase(unique(all(seq)), seq.end());
        int tot = seq.size(), ans = 0;
        repi(i, 0, tot - 1)num[seq[i]] = i + 1;
        repi(i, 1, n) {
            a[i] = num[a[i]], cnt[a[i]]++, st[a[i]].insert(i);
            b[i] = num[b[i]], cnt[b[i]]++, st[b[i]].insert(i);
        }
        repi(i, 1, tot)if (cnt[i] == 1)q.push(i);
        while (!q.empty()) {
            int x = q.front();
            q.pop();
            if (!cnt[x])continue;
            int pos = *st[x].begin();
            ans++, st[a[pos]].erase(pos), st[b[pos]].erase(pos);
            if (!--cnt[a[pos]])tot--;
            if (!--cnt[b[pos]])tot--;
            if (cnt[a[pos]] == 1)q.push(a[pos]);
            if (cnt[b[pos]] == 1)q.push(b[pos]);
        }
        printf("Case #%d: %d\n", ++cse, ans + tot);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_sky123_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值