拓扑排序 SRM 660 Div2 Medium: PrivateD2party

Problem Statement

Hero is inviting his friends to the party.

He has n friends, numbered 0 through n-1. For each of his friends there is at most one other person the friend dislikes. You are given this information as a int[] a with n elements. For each i, a[i] is either the number of the person disliked by friend i, we have a[i]=i if friend i likes everybody else.

Hero is inviting his friends one at a time. Whenever he invites friend i, they will accept if and only if the friend a[i] didn't accept an earlier invitation. (That includes two cases: either Hero didn't invite friend a[i] yet, or he did but the friend rejected the invitation.)

Hero noticed that the order in which he invites his friends matters: different orders may produce different numbers of accepted invitations.

Find an order that will produce the most accepted invitations, and return their number.

Definition

  • ClassPrivateD2party
  • Methodgetsz
  • Parametersvector<int>
  • Returnsint
  • Method signatureint getsz(vector<int> a)
(be sure your method is public)

Limits

  • Time limit (s)2.000
  • Memory limit (MB)256

Constraints

  • a will contain exactly n elements.
  • n will be between 1 and 50, inclusive.
  • Each element of a will be between 0 and n - 1, inclusive.

Test cases

    • a{ 0, 1 }
    Returns 2
    Each of the friends likes the other. Regardless of the order in which Hero asks them, they will both accept the invitation.
    • a{ 1, 0 }
    Returns 1
    Friend 0 dislikes friend 1 and vice versa. The first friend Hero asks will accept the invitation but then the other friend will certainly reject it.
    • a{ 1, 0, 3, 2 }
    Returns 2
    • a{ 5, 2, 2, 4, 5, 0 }
    Returns 5
    Here is what would happen if Hero invited the friends in the order (0,1,2,3,4,5):
    • Friend 5 didn't accept yet, so friend 0 would accept.
    • Friend 2 didn't accept yet, so friend 1 would accept.
    • Friend 2 likes everybody and therefore they would accept.
    • Friend 4 didn't accept yet, so friend 3 would accept.
    • Friend 5 didn't accept yet, so friend 4 would accept.
    • Friend 0 did already accept, therefore friend 5 would reject.
    It turns out that this solution happens to be optimal: there is no order such that all six friends would accept the invitations.
    • a{ 3, 2, 1, 0, 5, 4 }
    Returns 3

题解

Imagine we wanted all friends to accept the invitation. This would mean that whenever a friend A dislikes a friend B, friend A must receive the invitation before B. Define "A must come before B" as a requirement: "B requires A" meaning that if we want to invite B, we must invite A first. Wording this as requirements makes us able to use knowledge about a known problem: Topological Sorting. If we represent the requirement "B requires A" as a graph in which there is an edge connecting B to A, then a topological sort exists if and only if the graph contains no cycles. This means that if the graph contains no cycles, we can actually find a way to have ALL the friends accept the invitation. We don't really need to know the order, but it is actually very intuitive: In each step, invite a person that is not disliked by anyone among the group of not-yet invited friends.

What happens when there are cycles? Each friend dislikes at most one other person. This means that if there is a cycle, the representation as a graph will feature a ring like :  abc...a . Each of these cycles would make a whole connected component. How can we maximize the number of friends in the cycle that accept the invitation? We know it is impossible to make all of them accept an invitation. So at least one of these friends won't accept the invitation, so let's pick a friend  x  to offer the invitation first. They will definitely reject the invitation, but now, we have a friend we can offer an invitation: The friend  x  disliked can now receive an invitation and accept because  x  is out of the picture. Then we can invite the friend that other friend disliked and so and so. Therefore, we can invite all the friends in the cycle but one.

For each cycle in the graph, there is one friend we cannot invite. Other connected components we can analyze as if they were a single graph with no cycles, meaning that we can invite all the people in that kind of connected component. Therefore, for each cycle in the graph, the number of friends we can invite is reduced by 1. This means that the result is  nnumber of cycles .

vector<int> mark, a;
 
// We can use a DFS to detect and count the cycles in the graph. The simple
// structure of the graphs in this problem also allow other ad hoc approaches
bool dfs(int x)
{
    if (a[x] == x) {
        return false;
    } else if (mark[x] == 0) {
        mark[x] = 2;
        bool rem = dfs(a[x]);
        mark[x] = 1;
        return rem;
    } else if (mark[x] == 2) {
        return true;
    }
    return false;
     
}
 
int getsz(vector<int> a)
{
    this->a = a;
    int n = a.size();
    mark  = vector<int>(n, 0);
     
    // Count cycles:
    int cyclecount = 0;
    for (int i = 0; i < n; i++) {
        if (mark[i] == 0) {
            if (dfs(i)) {
                cyclecount++;
            }
        }
    }
     
    // the result
    return n - cyclecount;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值