POI2008 Mafia

POI2008 Mafia

Subject to the effect:

There are n individuals, everyone has a gun. At first, all of them selected a person sighting (it is possible to aim its own). Then they follow a certain sequence shot, and at any time only one person shot. Therefore, for a different shot sequence, the last dead person is different. Ask the minimum and maximum possible value of the final death toll.

( $nle 10^6$ )

answer:

First, it is easy to see that map is a ring outward tree, then we can use some tree ring outward to the nature of the problem-solving.

For the greatest possible number of people, we get better. At least as long as the number of surviving on it, then let those who are dead will not survive, others can kill.

People will not die in two ways:

  1. The degree to 0 people. Since no one aiming a gun at them, apparently will not die.
  2. When a ring no outward tree "branches", and that only a middle ring, there is no way we will kill all the people on the ring finished, always leave a. He left that you can not die. (Intermediate ring is not self-loop, or could conceivably kill people on the ring End)

Topological sorting out just a bit, this part can be solved.

Then take a look at the smallest possible number of people:

A person will not die key to see if a person did not die of a gun at him.

That is, if a person did not die, so he refers to the people who will die.

First, the degree zero of people, certainly not die, but he refers to the people who will all die.

In order for the living as much as possible, we might as well let the dead people do not shoot.

Then for a mortal man, he aimed at people who have less chance of being killed, we can put them into degrees minus one.

If the degree of reduction to zero, indicating that all threats are excluded, who has been a die.

Thus, we can ring outward tree "branches" all cleared away.

For leaving the ring, a ring on any of our people from the beginning, let him die, then loop it can flow again.


In fact, the minimum can also be used to write dp tree.

Topic transforming what can be changed to:

We put the tree ring outward edges have become bidirectional. Then take some point in the tree (which represents the point alive), and the two adjacent points can not be taken, to maximize the number of points taken.


Code:

      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
      
      
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
void (int&res){
res= 0; char c;
while(c=getchar(),c< 48);
do res=res* 10+(c& 15);
while(c=getchar(),c> 47);
}
const int N = 1000005 ;
int n, aim [N] cnt [N] years;
bool used[N];
void work(int p,int c){
if(used[p]) return;
used[p]= true;
ans+=c;
if(!(--cnt[aim[p]])||c)work(aim[p],c^ 1);
}
int solve_min(){
ans= 0;
memset(cnt, 0, sizeof(cnt));
memset(used, 0, sizeof(used));
for( int i= 1;i<=n;i++)cnt[aim[i]]++;
for( int i= 1;i<=n;i++)
if(!cnt[i])work(i, 1);
for( int i= 1;i<=n;i++)work(i, 0);
return n-ans;
}
queue< int>que;
void check_loop(int p){
bool flag= false;
for( int pre=p;flag|=used[p],aim[p]!=pre;cnt[aim[p]]--,p=aim[p]);
if(!flag)ans++;
}
int solve_max(){
ans= 0;
memset(cnt, 0, sizeof(cnt));
memset(used, 0, sizeof(used));
for( int i= 1;i<=n;i++)cnt[aim[i]]++;
while(!que.empty())que.pop();
for( int i= 1;i<=n;i++)
if(!cnt[i])que.push(i),ans++;
while(!que.empty()){
int p=que.front();que.pop();
if(!(--cnt[aim[p]]))que.push(aim[p]);
else used[aim[p]]= true;
}
for( int i= 1;i<=n;i++)
if(cnt[i]&&i!=aim[i])check_loop(i);
return n-ans;
}
int solve () {
printf( "%d %dn",solve_min(),solve_max());
return 0;
}
int main(){
Rd (n);
for( int i= 1;i<=n;i++)Rd(aim[i]);
return solve();
}

Original: Big Box  POI2008 Mafia


Guess you like

Origin www.cnblogs.com/wangziqiang123/p/11618256.html