Sicily 7531. Chains 解题报告
题目:
Constraints
Time Limit: 1 secs, Memory Limit: 256 MB
Description
Mirko has found N chains in his attic. Each chain consists of some number of links, where each link has at most two adjacent links. Each link can be opened or closed, so it is possible to separate chains or connect them into a longer chain. Mirko would like to connect all chains into one huge chain, while opening and closing as few links as possible.
For example, if Mirko has only three chains, each consisting of only one
link, he can open one of them, use it to connect the remaining two and
close it:
Given the number of chains and the length of each chain, find the minimum number of links that Mirko has to open and close in order to bind them all in one long chain.
Input
The first line of input contains the positive integer N (2 ≤ N ≤ 500 000), the number of chains.
The second line of input contains N positive integers Li (1 ≤ Li ≤ 1 000 000), the lengths of individual chains.
Output
The first and only line of output must contain the required minimum number of links.
Sample Input
样例1: 2 3 3 样例2: 3 1 1 1 样例3: 5 4 3 5 7 9
Sample Output
样例1: 1 样例2: 1 样例3: 3
Hint
Clarification of the first example: Mirko can open the last link of the first chain, connect it with the first link of the second chain and close it.
Clarification of the third example: Here it is best to completely take
apart the chain of length 3, using its three links to connect the
remaining chains.
分析:
由题目样例2可以得到启发,当一个链条只剩最后1个环时,将其打断可以达到最好的效果,使总链条数减少2,而其他情况打断一个环只能使总链条数减少1,因此从最优的方面考虑每次都选环数最少的链条来打断。因此首先对链条进行排序,然后从小到大的打断链条,每次打断后更新总的链条数num_of_chains和需要打断的环数count,当总链条数大于1的时候进行循环。
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 using namespace std; 5 int chains_to_be_connected[500000]; 6 7 int main(){ 8 int num_of_chains; //链条数 9 int count=0; //需要打断的节数 10 scanf("%d",&num_of_chains); 11 for(int i=0;i<num_of_chains;i++) 12 scanf("%d",&chains_to_be_connected[i]); 13 sort(chains_to_be_connected,chains_to_be_connected+num_of_chains);//链条从小到大排序 14 int subscript=0;//初始化指向最短的链条,用完后移动到第二短的,以此类推 15 while(num_of_chains>1){//最后合并成为1条 16 if(num_of_chains<=chains_to_be_connected[subscript]){//无需将最短那条完全打断就能全部连成一条 17 count+=(num_of_chains-1);//例如还剩n条,则只需打断n-1个环 18 break; 19 }else{//将最短那条n个环完全打断可以使总数减少n+1条 20 count+=chains_to_be_connected[subscript]; 21 num_of_chains-=(chains_to_be_connected[subscript]+1); 22 subscript++; 23 } 24 } 25 printf("%d\n",count); 26 return 0; 27 }