2016湖南湘潭邀请赛题解:2016年“长城信息”杯中国大学生程序设计比赛中南地区邀请赛(迟来的题解)

2016湖南湘潭邀请赛题解:2016年“长城信息”杯中国大学生程序设计比赛中南地区邀请赛(迟来的题解)

提交OJ:http://202.197.224.59/OnlineJudge2/index.php/Problem/index/p/13/

题号:xtu 1243-1252

xtu 1243  A题  2016

2016

Given a 2×2 matrix

A=(a11a21a12a22),

find An where A1=A,An=A×An1. As the result may be large, you are going to find only the remainder after division by 7.

 

Special Note: The problem is intended to be easy. Feel free to think why the problem is called 2016 if you either:

  1. find it hard to solve;
  2. or, solved all the other problems easily.

Input

The input contains at most 40 sets. For each set:

The first line contains an integer n (1n<10100000).

The second line contains 2 integers a11,a12.

The third line contains 2 integers a21,a22.

(0aij<7, (a11a22a12a21) is not a multiple of 7)

Output

For each set, a 2×2 matrix denotes the remainder of An after division by 7.

Sample Input

2
1 1
1 2
2016
1 1
1 2

Sample Output

2 3
3 5
1 0
0 1
思路:大数取模+矩阵乘法;
AC代码:
#include 
#include <string.h>
const int M=500000;
int a[M][2][2];
char s[M];
int main()
{
    int n;
    while(scanf("%s",s)!=EOF)
    {
      int mod=0,n=0,x1,y1,x2,y2,len=strlen(s);
      scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
      a[1][0][0]=a[0][0][0]=x1;
      a[1][0][1]=a[0][0][1]=y1;
      a[1][1][0]=a[0][1][0]=x2;
      a[1][1][1]=a[0][1][1]=y2;
      for(int i=2;i<=M;i++)
      {
          mod++;
          a[i][0][0]=(a[i-1][0][0]*x1+a[i-1][0][1]*x2)%7;
          a[i][0][1]=(a[i-1][0][0]*y1+a[i-1][0][1]*y2)%7;
          a[i][1][0]=(a[i-1][1][0]*x1+a[i-1][1][1]*x2)%7;
          a[i][1][1]=(a[i-1][1][0]*y1+a[i-1][1][1]*y2)%7;
          if(a[i][0][0]==x1&&a[i][0][1]==y1&&a[i][1][0]==x2&&a[i][1][1]==y2)
            break;
      }
      a[0][0][0]=a[mod][0][0];
      a[0][0][1]=a[mod][0][1];
      a[0][1][0]=a[mod][1][0];
      a[0][1][1]=a[mod][1][1];
      for(int i=0;i)
        n=(n*10+s[i]-'0')%mod;
      printf("%d %d\n%d %d\n",a[n%mod][0][0],a[n%mod][0][1],a[n%mod][1][0],a[n%mod][1][1]);
    }
    return 0;
}

 

xtu 1244  B题  Gambling

Gambling

In ICPCCamp, gambling is conducted as follow. A player will draw balls from an opaque bag containing a red balls, b green balls and c blue balls initially. Balls in the bag will be drawn in equal probability while drawn balls won't be put back into the bag. The player continues the process until he collects all a red balls, or all b green balls, or all c blue balls. He ends up with First Prize if he collects a red balls, or Second Prize if he collects b green balls, or Third Prize otherwise.

Bobo is going to take part in the above gambling. Therefore, it is very important for him to work out the probability of winning each prize.

Input

The input contains at most 40 sets. For each set:

Three integers a,b,c (1a,b,c103).

Output

For each set, three irreducible fractions pA,pB,pC denote the probability of winning First Price, Second Price, and Third Price, respectively.

Sample Input

1 1 1
1 2 3

Sample Output

1/3 1/3 1/3
7/12 4/15 3/20

题意:
有a个红球,b个绿球,c个黄球,先拿完a个红球一等奖,先拿完b个绿球二等奖,c个黄球三等奖。求各个奖获奖的概率。

 

思路:

分析首先拿完红球,即拿一等奖的概率:

我们假设拿完红球后继续拿,也就是拿完所有的球。

接下来逆向思考,红球不可能是最后一个,最后一个只可能是黄球或绿球,我们可以把摸出来的球的顺序逆置,比如(红,黄,红,绿,绿,黄,绿)逆置之后就是(绿,黄,绿,绿,红,黄,红),你会发现,你第一个摸到的球的颜色一定会是黄、绿当中的一种,而摸到的第二种颜色的球一定是黄绿当中未摸到过的,这样的话就很好计算了。

那么如果最后一个球是黄球,它的概率就是c/(a+b+c),除去黄球,最后一个是绿球的概率就是b/(a+b)。此时概率就是两者相乘。

最后一个球是绿球的话也是这样分析。

二等奖和三等奖也如上分析即可。


AC代码 :
#include
#include
#include
#include
using namespace std;
typedef long long LL;
LL a,b,c;
LL gcd(LL a,LL b)
{
    return b==0?a:gcd(b,a%b);
}
void cacl(LL a, LL b, LL c,int flag)
{
    LL z=b*c*(2*a+b+c);
    LL m=(a+b+c)*(a+b)*(a+c);
    LL g=gcd(m,z);
    printf("%I64d/%I64d",z/g,m/g);
    if(flag<=2)  printf(" ");
    else printf("\n");
}

int main()
{
    while(~scanf("%lld%lld%lld",&a,&b,&c))
    {
        cacl(a,b,c,1);
        cacl(b,a,c,2);
        cacl(c,a,b,3);
    }
    return 0;
}

 

 

xtu 1245  C题  Hamiltonian Path

Hamiltonian Path

In ICPCCamp, there are n cities and m directed roads between cities. The i-th road going from the ai-th city to the bi-th city is ci kilometers long. For each pair of cities (u,v), there can be more than one roads from u to v.

Bobo wants to make big news by solving the famous Hamiltonian Path problem. That is, he would like to visit all the n cities one by one so that the total distance travelled is minimized.

Formally, Bobo likes to find distinct integers p1,p2,,pn to minimize w(p1,p2)+w(p2,p3)++w(pn1,pn) where w(x,y) is the length of road from the x-th city to the y-th city.

Input

The input contains at most 30 sets. For each set:

The first line contains 2 integers n,m (2n105,0m105).

The i-th of the following m lines contains 3 integers ai,bi,ci (1ai<bin,1ci104).

Output

For each set, an integer denotes the minimum total distance. If there exists no plan, output -1 instead.

Sample Input

3 3
1 2 1
1 3 1
2 3 1
3 2
1 2 1
1 3 2

Sample Output

2
-1

思路:只能1-2-3-4-。。。-n;1ai<bin。。。

AC代码:
#include 
#include 
#include 
#include 
using namespace std;
const int M=100000+10;
int a[M];
int main()
{
    int n,m;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
     memset(a,0,sizeof(a));
     int sum=0,k=0;
     for(int i=1;i<=m;i++)
     {
         int x,y,c;
         scanf("%d %d %d",&x,&y,&c);
         if(y==x+1)
         {
            if(a[x]==0)
            {
                a[x]=c;
                k++;
            }
            else
                a[x]=min(a[x],c);
         }
     }
     if(k

  

xtu 1246  D题  Heartstone
Heartstone

Bobo is playing Heartstone. There are n minions in the battlefield. The i-th minion has hi hit points (HP).

Bobo uses two kinds of magic. The one is Arcane Shot and the other is FrostboltArcane Shot can deal two points damage to a minion (that is to decrease the minion's HP by two), while Frostbolt can deal three points damage. A minion is killed when its HP is less or equal to zero.

Let f(a) be the minimum number of Frostbolt(s) required to kill all minions, if no more than Arcane Shot(s) are used. Bobo would like to find out f(0)+f(1)++f(m) modulo (109+7).

Input

The input contains at most 30 sets. For each set:

The first line contains 2 integers n,m (1n105,0m105).

The second line contains n integers h1,h2,,hn (1hi104).

Output

For each set, an integer denotes f(0)+f(1)++f(m) modulo (109+7).

Sample Input

3 2
1 2 3
3 2
2 2 2

Sample Output

6
6

题意+思路(借鉴他人):

炉石游戏,有A 和F魔法,问给你n个带血量的小兵,你在每次最多拥有f(0)…f(m)个A魔法,f(0)代表最多有0个A魔法,的情况下,最少需要几个F魔法才能击杀所有的小兵

要控制魔法F的使用就要控制好A魔法的使用,优先队列加栈,x%3小的优先,x%3相等时,小的优先。

AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

typedef long long LL;

const int MOD=1e9+7;

int n,m;

struct node
{
    int h;
    bool operator < (const node &b)const
    {
        return h%3 q;
        for(int i=0;i0)
                 num2=x.h/3+(x.h%3==0?0:1);
            else num2=0;
            if(x.h)  q.push(x);
            sum=sum-(num1-num2);
            ans=(ans+sum)%MOD;
        }
        printf("%lld\n",ans);
    }
}

  

xtu 1247  E题  Pair - pair

Pair-Pair

Bobo is tired of all kinds of hard LIS (Longest Increasing Subsequence) problems, so he decides to make himself some easier one.

Bobo has n pairs (a1,b1),(a2,b2),,(an,bn) where 1ai,bim holds for all i. He defines f(i,j) be the length of longest increasing subsequence of sequence {ai,bi,aj,bj}.

It's clear that 1f(i,j)4. Bobo would like to know g(k) which is the number of pairs (i,j) where f(i,j)=k.

Note that a sequence labeled with {i1,i2,,ik} is an increasing subsequence of {a1,a2,,an} only if:

  • 1i1<i2<<ikn
  • ai1<ai2<<aik

Input

The input contains at most 30 sets. For each set:

The first line contains 2 integers n,m (1n105,1m103).

The i-th of the following n lines contains 2 integers ai,bi (1ai,bim).

Output

For each set, 4 integers g(1),g(2),g(3),g(4).

Sample Input

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

Sample Output

0 3 0 1
4 0 0 0
分析:开个1000*1000的数组,预处理矩阵和,然后分类讨论就好(借鉴他人)

AC代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long LL;
const int N=1e5+5;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
struct Node{
  int x,y;
}p[N];
int a[1005][1005];
int high[1005],low[1005],mid[1005];
LL ret[5];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m)){
      memset(a,0,sizeof(a));
      memset(ret,0,sizeof(ret));
      memset(high,0,sizeof(high));
      memset(low,0,sizeof(low));
      memset(mid,0,sizeof(mid));
      for(int i=1;i<=n;++i){
         scanf("%d%d",&p[i].x,&p[i].y);
         ++a[p[i].x][p[i].y];
         if(p[i].y>p[i].x)++high[p[i].x];
         else if(p[i].y==p[i].x)++mid[p[i].x];
         else ++low[p[i].x];
      }
      for(int i=1;i<=m;++i){
        low[i]+=low[i-1];
        mid[i]+=mid[i-1];
        high[i]+=high[i-1];
      }
      for(int i=1;i<=m;++i)
        for(int j=1;j<=m;++j)
          a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
      for(int i=1;i<=n;++i){
        if(p[i].y>p[i].x){
             int tmp=0,t;
             t=high[m]-high[p[i].y];
             tmp+=t;ret[4]+=t;
             t=low[m]-low[p[i].y]+mid[m]-mid[p[i].y];
             tmp+=t;ret[3]+=t;
             t=high[p[i].y]-high[p[i].y-1];
             tmp+=t;ret[3]+=t;
             t=high[p[i].y-1]-high[p[i].x];
             tmp+=t;ret[3]+=t;
             t=a[p[i].x][m]-a[p[i].x][p[i].y];
             tmp+=t;ret[3]+=t;    
             ret[2]+=1ll*(n-tmp);
        }
        else if(p[i].x==p[i].y){
          int tmp=0,t;
          t=high[m]-high[p[i].x];
          tmp+=t;ret[3]+=t;
          t=low[p[i].x]+mid[p[i].x];
          tmp+=t;ret[1]+=t;
          ret[2]+=1ll*(n-tmp);
        }
        else {
          int tmp=0,t;
          t=low[p[i].y]+mid[p[i].y];
          tmp+=t;ret[1]+=t;
          t=high[m]-high[p[i].y];
          tmp+=t;ret[3]+=t;
          ret[2]+=1ll*(n-tmp);
        }
      }
      printf("%I64d %I64d %I64d %I64d\n",ret[1],ret[2],ret[3],ret[4]);
    }
    return 0;
}

 

xtu 1248  F题  Tc or CF
TC or CF

There are n contests going to be held in the upcoming year. However, the committee keeps debating whether the contest is of TC (Thinking Creatively) style or CF (Coding Fast) style.

The committee knows in advance that there are m contestants who take part in exactly two contests. The i-th contestant will join the ai-th contest and then the bi-th contest. Note that contests are held in parallel so that there may exist two contestants i and j where ai=bj,bi=aj.

If the i-th contestant takes a TC-style contest then a CF-style contest, he or she will feel ci points of unhappiness. Otherwise he will not feel unhappy. Therefore, the committee will decides the types of contests according to the following 3 rules:

  • There are at least 3 TC-style contests, and the first contest (1-st) should be TC-style.
  • There are also at least 3 CF-style contests, and the last contest (n-th) should be CF-style.
  • The total unhappiness of contestants is minimized.

Input

The input contains at most 30 sets. For each set:

The first line contains 2 integers n,m (6n50,0m500).

The i-th of the following m lines contains 3 integers ai,bi,ci (1ai,bin,aibi,1ci1000).

Output

For each set, an integer denotes the minimum of total unhappiness.

Sample Input

6 5
1 6 100
1 3 1
1 4 1
2 3 1
2 4 1
6 12
2 3 1
2 4 1
2 5 1
3 2 1
3 4 1
3 5 1
4 2 1
4 3 1
4 5 1
5 2 1
5 3 1
5 4 1

Sample Output

100
4

本题网上暂未找到AC代码 出题方题解
2016湖南湘潭邀请赛题解:2016年“长城信息”杯中国大学生程序设计比赛中南地区邀请赛(迟来的题解)_第1张图片

 

 
       
此题暂时无代码

 

 

xtu 1249  G题  Rolling Variance 

Rolling Variance

Bobo learnt that the variance of a sequence a1,a2,,an is

ni=1(aia¯)2n1−−−−−−−−−−−−√

where

a¯=ni=1ain.

 

Bobo has a sequence a1,a2,,an, and he would like to find the variance of each consecutive subsequences of length m. Formally, the i-th (1inm+1) rolling variance ri is the variance of sequence {ai,ai+1,,ai+m1}.

Input

The input contains at most 30 sets. For each set:

The first line contains 2 integers n,(2mn105).

The second line contains n integers a1,a2,,an (|ai|100).

Output

For each set, (nm+1) lines with floating numbers r1,r2,,rnm+1.

Your answer will be considered correct if its absolute or relative error does not exceed 104.

Sample Input

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

Sample Output

 

1.41421356
0.70710678
1.00000000
1.00000000
1.52752523

思路:前缀和

AC代码:

#include 
#include 
#include 
#include 
using namespace std;
const int M=100000+10;
double a[M],b[M];
int main()
{
    int n,m;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
     a[0]=b[0]=0;
     for(int i=1;i<=n;i++)
     {
        double x;
        scanf("%lf",&x);
        a[i]=a[i-1]+x;
        b[i]=b[i-1]+x*x;
     }

     for(int i=m;i<=n;i++)
     {
         double av=0,s=0;
         av=((a[i]-a[i-m])/(1.0*m));
         s=((b[i]-b[i-m])+m*av*av-2*av*(a[i]-a[i-m]))/(m-1);
         printf("%.8lf\n",sqrt(s));
     }
    }
    return 0;
}

  

xtu 1250  H题  Super Fast Fourier Transform 

Super Fast Fourier Transform

Bobo has two sequences of integers {a1,a2,,an} and {b1,b2,,bm}. He would like to find

i=1nj=1m|aibj|−−−−−−−√.

 

Note that x⌋ denotes the maximum integer does not exceed x, and |x| denotes the absolute value of x.

Input

The input contains at most 30 sets. For each set:

The first line contains 2 integers n,m (1n,m105).

The second line contains n integers a1,a2,,an.

The thrid line contains m integers b1,b2,,bm.

(ai,bi0,a1+a2++an,b1+b2+,bm106)

Output

For each set, an integer denotes the sum.

Sample Input

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

Sample Output

2
7

思路:不同的数最多1000个,c++11交

AC 代码:

#include 
#include 
#include 
#include 
#include 
using namespace std;
const int M=1000000+10;
int  a[M],b[M],c[M],d[M];
typedef long long ll;
ll sum=0;
int main()
{
    int n,m;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
      memset(c,0,sizeof(c));
      memset(d,0,sizeof(d));
      int k1=0,k2=0;
      sum=0;
      for(int i=0;i

 

xtu 1251  I题  Substring Query 

Substring Query

Given a string s1,s2,,sn of length n, Bobo is going to perform q operations of the following 2 kinds:

  1. to change the i-th character of the string (i.e. si) into c;
  2. to query how many times does p occur as substring of s. That is, count the number of indices i such that 1inm+1 and sisi+1,si+m1=p1p2pm.

Find out the result of each opeartion of the second kind.

Input

The input contains at most 10 sets. For each set:

The first line contains 2 integers n,q (1n5×104,1q105).

The second line contains a string s1s2,sn of lowercase characters.

The i-th of the last q lines may: 1. contains an integer ki and a lowercase character ci, which denote an operation to change the ski into ci (1kin). 2. contains an 0 followed by a string p1,p2,,pli of lowercase characters, which denote an operation to query the number of times that p1,p2,,pli occurs as a substring (li1,ili5×104).

Output

For each operation of second kind in each set, an integer denotes the number of substrings.

Sample Input

5 5
aaaaa
0 aa
2 b
0 aba
4 b
0 aba
1 1
a
0 a

Sample Output

4
1
2
1

分析:AC自动机+分块

AC代码:

#include 
using namespace std ;

#define clr( a , x ) memset ( a , x , sizeof a )

const int MAXN = 100005 ;
const int MAXQ = 100005 ;
const int SQR1 = 128 ;
const int SQR2 = 256 ;

vector < int > G[MAXN] ;
char s[MAXN] , ss[MAXN] ;
string p[MAXQ] ;
int op[MAXQ] ;
int nxt[MAXN][26] , fail[MAXN] , idx[MAXN] , in[MAXN] , ou[MAXN] , point , root , dfs_clock ;
int c[1000] , val[MAXN] ;
int n , m ;
int Q[MAXN] , l , r ;

int newnode () {
    clr ( nxt[point] , 0 ) ;
    return point ++ ;
}

void init () {
    point = 0 ;
    root = newnode () ;
}

void insert ( string& s , int n , int id ) {
    int u = root ;
    for ( int i = 0 ; i < n ; ++ i ) {
        int x = s[i] - 'a' ;
        if ( !nxt[u][x] ) nxt[u][x] = newnode () ;
        u = nxt[u][x] ;
    }
    idx[id] = u ;
}

void dfs ( int u ) {
    in[u] = ++ dfs_clock ;
    for ( int i = 0 ; i < G[u].size () ; ++ i ) dfs ( G[u][i] ) ;
    ou[u] = dfs_clock ;
}

void build () {
    l = r = 0 ;
    fail[root] = root ;
    for ( int i = 0 ; i < 26 ; ++ i ) {
        if ( !nxt[root][i] ) nxt[root][i] = root ;
        else {
            fail[Q[r ++] = nxt[root][i]] = root ;
            G[root].push_back ( nxt[root][i] ) ;
        }
    }
    while ( l != r ) {
        int u = Q[l ++] ;
        for ( int i = 0 ; i < 26 ; ++ i ) {
            if ( !nxt[u][i] ) nxt[u][i] = nxt[fail[u]][i] ;
            else {
                fail[Q[r ++] = nxt[u][i]] = nxt[fail[u]][i] ;
                G[nxt[fail[u]][i]].push_back ( nxt[u][i] ) ;
            }
        }
    }
    dfs_clock = 0 ;
    dfs ( root ) ;
}

inline void add ( int x , int v ) {
    c[x / SQR2] += v ;
    val[x] += v ;
}

int sum ( int x , int y ) {
    int L = x / SQR2 + 1 ;
    int R = y / SQR2 - 1 ;
    int ans = 0 ;
    if ( R + 1 <= L ) {
        for ( int i = x ; i <= y ; ++ i ) {
            ans += val[i] ;
        }   
    } else {
        for ( int i = L ; i <= R ; ++ i ) {
            ans += c[i] ;
        }
        L *= SQR2 ;
        R *= SQR2 ;
        for ( int i = x ; i < L ; ++ i ) {
            ans += val[i] ;
        }
        for ( int i = R + SQR2 ; i <= y ; ++ i ) {
            ans += val[i] ;
        }
    }
    return ans ;
}

int getpos ( char s[] , int L , int R ) {
    int u = root ;
    for ( int i = L ; i < R ; ++ i ) {
        int x = s[i] - 'a' ;
        u = nxt[u][x] ;
    }
    return u ;
}

void addv ( char s[] , int L , int R , int v , int now ) {
    int u = now ;
    for ( int i = L ; i < R ; ++ i ) {
        int x = s[i] - 'a' ;
        u = nxt[u][x] ;
        add ( in[u] , v ) ;
    }
}

void get_fail ( char p[] , int m ) {
    fail[1] = 0 ;
    for ( int i = 2 , j = 0 ; i <= m ; ++ i ) {
        while ( j && p[i] != p[j + 1] ) j = fail[j] ;
        if ( p[i] == p[j + 1] ) ++ j ;
        fail[i] = j ;
    }
}

int kmp ( char s[] , int n , char p[] , int m ) {
    int ans = 0 ;
    for ( int i = 0 , j = 0 ; i < n ; ++ i ) {
        while ( j && s[i] != p[j + 1] ) j = fail[j] ;
        if ( s[i] == p[j + 1] ) {
            ++ j ;
            if ( j == m ) {
                ++ ans ;
                j = fail[j] ;
            }
        } else j = fail[j] ;
    }
    return ans ;
}

void solve () {
    init () ;
    for ( int i = 0 ; i < m ; ++ i ) {
        scanf ( "%d" , &op[i] ) ;
        cin >> p[i] ;
        if ( op[i] == 0 && p[i].length () <= SQR1 ) insert ( p[i] , p[i].length () , i ) ;
    }
    for ( int i = 0 ; i < point ; ++ i ) {
        G[i].clear () ;
    }
    build () ;
    clr ( c , 0 ) ;
    clr ( val , 0 ) ;
    addv ( s , 0 , n , 1 , root ) ;
    for ( int i = 0 ; i < m ; ++ i ) {
        if ( op[i] ) {
            -- op[i] ;
            int L = max ( 0 , op[i] - SQR1 ) , R = min ( n , op[i] + SQR1 ) ;
            int now = getpos ( s , L , op[i] ) ;
            addv ( s , op[i] , R , -1 , now ) ;
            s[op[i]] = p[i][0] ;
            addv ( s , op[i] , R , 1 , now ) ;
        } else {
            if ( p[i].length () > SQR1 ) {
                int len = 0 ;
                for ( int j = 0 ; j < p[i].length () ; ++ j ) {
                    ss[++ len] = p[i][j] ;
                }
                get_fail ( ss , len ) ;
                printf ( "%d\n" , kmp ( s , n , ss , len ) ) ;
            } else {
                int ans = sum ( in[idx[i]] , ou[idx[i]] ) ;
                printf ( "%d\n" , ans ) ;
            }
        }
    }
}

int main () {
    while ( ~scanf ( "%d%d%s" , &n , &m , s ) ) solve () ;
    return 0 ;
}

  

xtu 1252  J题  Defense Tower

Defense Tower

In ICPCCamp, there are n cities and (n1) (bidirectional) roads between cities. The i-th road is between the ai-th and bi-th cities. It is guaranteed that cities are connected.

In the i-th city, there is a defense tower with power pi. The tower protects all cities with a road directly connected to city i. However, the tower in city i does not protect city i itself.

Bobo would like to destroy all defense towers. When he tries to destroy the tower in city i, any not-destroyed tower protecting city i will deal damage whose value equals to its power to Bobo.

Find out the minimum total damage Bobo will receive if he chooses the order to destroy the towers optimally.

Input

The input contains at most 30 sets. For each set:

The first line contains an integer n (1n105).

The second line contains n integers p1,p2,,pn (1pi104).

The i-th of the last (n1) lines contains 2 integers ai,bi (1ai,bin).

Output

For each set, an integer denotes the minimum total damage.

Sample Input

3
1 2 3
1 2
2 3
3
1 100 1
1 2
2 3

Sample Output

3
2

思路:考虑每条边对玩家的伤害

         假设连接的节点是u,v,破坏力是p[u]和p[v]

         假设p[u]>p[v]

         现在考虑u,v的删除顺序,如果先删u,这条边对玩家的伤害,是p[v],先删v,伤害是p[u]

         所以显然对于每条边,我们都要先删权值大的,才能最好

         怎么样才能对于每条边先删最大的呢,那就按照权值递减删就好了

         所以 ret=Σ(min(p[u],p[v]))

        复杂度O(n)

AC代码:

#include 
#include 
#include 
#include 
using namespace std;
const int M=100000+10;
int p[M];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
     int sum=0;
     for(int i=1;i<=n;i++)
     {
         scanf("%d",&p[i]);
     }

     for(int i=1;i

  

 

---恢复内容结束---

你可能感兴趣的:(2016湖南湘潭邀请赛题解:2016年“长城信息”杯中国大学生程序设计比赛中南地区邀请赛(迟来的题解))