您的位置:首页 > 其它

有向图判环+拆解图求参会期望 SRM 660 Div1 Medium: Privateparty

2015-08-05 19:31 387 查看
题意:N个参加聚会,和一个数组a,ai表示第i个人讨厌的人,如果一个到聚会门口的时候发现他讨厌的人已经在聚会里面,则他不会参加聚会,否则他会参加聚会。ai==i表示他没有讨厌的人。N个人来的先后顺序是任意的,也就是说n个来的先后顺序构成的1到n的排列是任意的。问参加聚会的人的期望是多少?


Privateparty


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. He thought about finding the best order but the task was too hard for him. Therefore he has decided that he will
invite his friends in a randomly chosen order. (Each permutation of his friends is equally likely to be chosen.)

Return the expected number of friends that will accept Hero's invitation.


Definition

ClassPrivateparty

Methodgetexp

Parametersvector<int>

Returnsdouble

Method signaturedouble getexp(vector<int> a)

(be sure your method is public)


Limits

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


Notes

Your solution is correct if the absolute error or the relative error is at most 10^-9.


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 }

Returns2.0

There are two friends. As a[0]=0 and a[1]=1, each friend likes the other. Regardless of the order of invitations, both will always accept.

a{ 0, 0 }

Returns1.5

In this test case friend 1 dislikes friend 0. If Hero invites 0 first and 1 next, 0 will accept and then 1 will reject. If Hero invites 1 first and 0 next, 1 will accept (as 0 didn't accept
yet) and then 0 will accept as well (because he likes 1).

a{ 0, 1, 1 }

Returns2.5

Now there are three friends. Friend 0 likes everybody else, friend 1 likes everybody else, and friend 2 dislikes friend 1.
Given three friends, there are six possible orders. Hero will choose one of these orders uniformly at random.

For example, if he invites them in the order (1,0,2), friend 1 will accept, friend 0 will accept, and friend 2 will reject the invitation. However, if he invites them in the order (2,1,0), all three friends will accept the invite.

a{ 0, 1, 1, 2 }

Returns3.166666666666667

a{ 3, 2, 1, 0 }

Returns2.0

题解

解:分开来计算每个人来参加聚会的期望,n个人来参加聚会的期望的和就是最后的答案。那么现在的问题是如何计算一个人来参加聚会的概率?
对于第i个人是否来参加聚会,受到一些人的影响,他们是:w1,w2,w3....wk。其中w1==i,w1讨厌w2,w2讨厌w3,...wk讨厌w1到wk-1的某个人。
我们对图中可能的情况进行拆解分析(循序渐进):

There are many possible approaches here including some that are very mathematical. Instead I'll explain one that is heavy code-wise but is interesting as it builds up from simple cases to general ones.

Let's make this into a graph. If a friend dislikes another friend, there is a directed edge connecting the hater to the hated. Like in the division 2 version, we can rely on there being a limited number of possible shapes. Let's
try each of them and see what we can do.


Lines

The simplest configuration would be sequence of friends who hate the next friend:



We can describe these situations by just the number of nodes. So imagine a function f(n) that
will tell us the expected number of friends that turn up when the graph is just a linear sequence of n friends.

For each friend, there is an 1n probability
that the friend is the first friend picked. Let's imagine what happens for each of those cases:



So we can try this for each node i.
When a friend is selected first, they will surely accept the invitation, so the count increases by 1. If there was any friend that hated them, that friend will never accept the invitation. The key is we can from now on ignore that both of these friends exist
and just calculate the expected values for the remaining structures, usually two new graphs that are linear sequences are created, we can use f() to
solve them. We divide the results of each of the n cases
by n,
because the probability for each of them is 1n.
Remember, the expected value is equal to the sum of each possible number multiplied by its probability. The base case is when n=1,
when there is only one friend, they always get invited. The iterative implementation is like this:
int n = a.size();
 
vector<double> line_expected(n + 1, 1.0);
 
line_expected[0] = 0.0;
line_expected[1] = 1.0;
line_expected[2] = 1.5;
for (int i = 3; i <= n; i++) {
    // last is picked:
    line_expected[i] = 1.0 + line_expected[i - 2];
    // first is picked:
    line_expected[i] += 1.0 + line_expected[i - 1];
    // second is picked:
    line_expected[i] += 1.0 + line_expected[i - 2];
     
    // the rest
    for (int j = 1; j < i - 2; j++) {
        line_expected[i] += 1.0 + line_expected[j] + line_expected[i - j - 2];
    }
    line_expected[i] /= i;
     
}
// line_expected
 now has the expected value for a linear sequence of size n



Rings

The second-simplest kind of graph we can find in this problem are rings:



In this case, notice the symmetry. All of the nodes will behave in a similar way. For the first friend, we will pick one of them, it doesn't matter which. The result is the cycle breaks:



The first node picked means a friend gets invited. The friend who hated them won't be invited. So now we have n−2 friends
making a linear graph like those in the last section. The expected value for a cycle is 1+f(n−2).
Where f is
the solution for the above section.


Armed rings

But enough easy structures, what about this?



This shape is a bit more complex but maybe we can still use the same method? Represent these "armed rings" by two integers: The length of the cycle and the length of the arm. The first friend picked might be any of the nodes. If
the node is in the arm, the reduction is easy:



This will typically split the graph into a linear sequence and an "armed ring" with a shorter arm. So we can reuse f() and
also solve the armed ring problem with a smaller arm now.

The start of the cycle is a more interesting case:



This will generate two linear sequences. One will have a length equal to the arm length minus 1 and the other a length equal to the cycle length minus 2.

Something similar happens when the friend that's hated by the start of the cycle is picked. Once again two linear sequences. Cutting other sections of the graph generates something more special:



This generates a Y-like shape. The good news is we can solve it too.


Y shape

We could use the same approach, this time make it an O(n3) state
by it having 3 arms. There is an easy way, however, we can make use of the linearity of expectation. The expected value of a sum is equal to the sum of the expected values of each summand. In this case, we can consider the total number of friends that accept
the invitation as a sum: For each friend, if friend accepts invitation add 1, else 0. Then the expected value is equal to the sum of each of those expected values. The definition of the expected value tells us that the expected value in this case is the probability
that each friend is accepted. Note the probabilities are not necessarily independent of each other, but that doesn't matter. The linearity of expectation still applies.

So if we wanted to find the expected number of friends that accept the invitation in a Y-shaped figure, we could calculate it as the sum of each probability the friend accepts an invitation. How is calculating these probabilities
easier? Consider this:



The probabilities that each red node accepts the invitation are independent of the blue nodes. If a blue node accepts the invitation or not it doesn't change the red nodes' ability to accept. So if we want to find the probabilities
for the red nodes, we can just consider a linear sequence of 6 nodes and calculate the probabilities.

We can go one step further and reuse the linearity of expectation. Remember that in the case of a linear sequence of 6 nodes, we already know how to calculate the expected number of friends that accept: f(6).
From this we can know that the sum of the probabilities for the 6 nodes is f(6).
Now consider this other linear sequence:



We can use the same logic and say that f(8) is
the sum of all probabilities for blue nodes. Now if we add f(6)+f(8) we
would get close to the sum of all probabilities in the whole graph, but there would be some repeated probabilities, the lower arm. We can just subtract it: f(4),
so we can just use : f(8)+f(6)−f(4) to
find the sum of probabilities in the graph, that is to say the expected value of the whole graph.

We can translate all of this into a dynamic programming approach that works for any arm and cycle length:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: