题解:P4520 [COCI 2017/2018 #4] Izbori

 题目描述

In a land with developed democracy far, far away, presidential elections for the football association are taking place. This land consists of N counties, and each county has its own football association. There are M presidential candidates labeled with 1, 2, … M. Each of the football associations will select exactly one candidate to cast their vote for. The winner of the election is the candidate with the most votes. If multiple candidates get the most amount of votes, the winner is the one with the smallest label.

During the election campaign, candidates visited the counties and tried to gain their sympathies. After having met all the candidates, each county’s football association determined the order in which they would cast their vote for each candidate.

For example, let’s assume that there are four candidates in the election and that one county’s order is 2, 1, 4, 3. This means that, unless they revoke their candidacy, the candidate with label 2 will get the county’s vote. If candidate 2 revokes their candidacy, and candidate 1 is still in the race, then they will get the vote, and so on.

Zdravko is a passionate football fan, and also a close friend of candidate with label K. He wants to know which candidate will win if neither of the candidates revokes their candidacy.

He also wants to know what is the minimal number of candidates he must persuade to revoke their candidacy in order for his friend, candidate K, to become the president of the football association.

Zdravko is currently dealing with other problems, so he is hoping that you will answer these questions.

翻译:

输入格式

The first line of input contains the numbers N (1 ≤ N ≤ 100), M (1 ≤ M ≤ 15) and K (1 ≤ K ≤ M) from the task.

Each of the following N lines contains the orders given by the counties’ football associations, i.e. a permutation of the first M natural numbers.

输出格式

You must output the answers to the questions from the task, each in its own line.

题目描述

在一个遥远的、民主高度发达的国家,足球协会的总统选举正在进行。这个国家由N个县组成,每个县都有自己的足球协会。共有M位总统候选人,分别标记为1, 2, …, M。每个足球协会将选择恰好一位候选人进行投票。选举的获胜者是获得最多票数的候选人。如果有多个候选人获得相同的最高票数,则标记最小的候选人获胜。

在竞选期间,候选人访问了各个县,试图赢得他们的支持。在见过所有候选人之后,每个县的足球协会确定了他们为每位候选人投票的顺序。

例如,假设选举中有四位候选人,某个县的投票顺序是2, 1, 4, 3。这意味着,除非候选人2退出竞选,否则候选人2将获得该县的投票。如果候选人2退出竞选,而候选人1仍在竞选中,那么候选人1将获得该县的投票,以此类推。

Zdravko是一位狂热的足球迷,也是标记为K的候选人的好朋友。他想知道如果没有任何候选人退出竞选,哪位候选人将获胜。

他还想知道,为了让他的朋友候选人K成为足球协会的总统,他必须说服的最少候选人退出竞选的数量是多少。

Zdravko目前正在处理其他问题,因此他希望你能回答这些问题。

输入格式

输入的第一行包含数字N(1 ≤ N ≤ 100)、M(1 ≤ M ≤ 15)和K(1 ≤ K ≤ M),分别表示县的数量、候选人的数量和Zdravko的朋友候选人的标记。

接下来的N行,每行包含一个县的足球协会给出的投票顺序,即前M个自然数的排列。

输出格式

你必须输出任务中的两个问题的答案,每个答案占一行。

  1. 第一行输出如果没有任何候选人退出竞选,哪位候选人将获胜。

  2. 第二行输出为了让候选人K获胜,Zdravko必须说服的最少候选人退出竞选的数量。

输入输出样例

输入 #1

3 4 1
3 4 1 2
4 2 3 1
3 4 2 1

输出 #1

3
3

输入 #2

4 1 1
1
1
1
1

输出 #2

1
0

输入 #3

4 4 4
2 3 1 4
2 3 1 4
1 3 2 4
4 3 2 1

输出 #3

2
3

题解 :

#include <bits/stdc++.h>
#define int long long
using namespace std;

// 计算当前选举的获胜者
int check(const vector<int> p) {
    int mx = *max_element(p.begin(), p.end());
    for (int i = 1; i <= p.size(); ++i) {
        if (p[i - 1] == mx) {
            return i; // 返回得票最多的候选人(编号最小优先)
        }
    }
    return -1;
}
// 模拟选举过程
pair<int, int> f(int n, int m, int k, const vector<vector<int> > b) {
    // 初始投票结果
    vector<int> p(m, 0);
    for (auto a : b) {
        for (int q : a) {
            if (find(b[0].begin(), b[0].end(), q) != b[0].end()) {
                p[q - 1] ++;
                break;
            }
        }
    }
    // 计算当前获胜者
    int flag = check(p);
    // 如果当前获胜者已经是k,则不需要说服任何人
    if (flag == k) return {flag, 0};
    // 否则,尝试说服最少的候选人退出竞选
    int mn = m; // 最多需要说服m-1个候选人
    for (int i = 0; i < (1 << m); ++i) {
        if (i & (1 << (k - 1))) continue; // 不能说服k退出竞选
        // 模拟说服后的投票
        vector<int> newVotes(m, 0);
        for (const auto& a : b) {
            for (int q : a) {
                if (!(i & (1 << (q - 1)))) { // 如果候选人没有被说服退出
                    newVotes[q - 1]++;
                    break;
                }
            }
        }
        // 检查k是否获胜
        if (check(newVotes) == k) {
            int x = __builtin_popcount(i); // 计算说服的候选人数量
            mn = min(mn, x);
        }
    }
    return {flag, mn};
}
signed main() {
    int n, m, k;
    cin >> n >> m >> k;
    vector<vector<int> > b(n);
    for (int i = 0; i < n; i ++) {
        b[i].resize(m);
        for (int j = 0; j < m; j ++) {
            cin >> b[i][j];
        }
    }
    auto ans = f(n, m, k, b);
    cout << ans.first << endl; // 当前获胜者
    cout << ans.second << endl; // 最少需要说服的候选人数量
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值