非常棒的题解,我就不复述了:http://blog.youkuaiyun.com/Bahuia/article/details/76141574
O(n)
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
ll ans;
bool vis[200010],hav[200010];
int sum[200010];
int v[400010],e,next[400010],first[200010];
void AddEdge(int U,int V){
v[++e]=V;
next[e]=first[U];
first[U]=e;
}
int n,c[200010],siz[200010];
void dfs(int U){
vis[U]=1;
siz[U]=1;
int allcU=0;
for(int i=first[U];i;i=next[i]){
if(!vis[v[i]]){
int tmp=sum[c[U]];
dfs(v[i]);
int add=sum[c[U]]-tmp;
siz[U]+=siz[v[i]];
ans+=(ll)(siz[v[i]]-add)*(ll)(siz[v[i]]-add-1)/2ll;
allcU+=(siz[v[i]]-add);
}
}
sum[c[U]]+=(allcU+1);
}
int main(){
int x,y,zu=0;
while(scanf("%d",&n)!=EOF){
++zu;
ans=0;
memset(sum,0,sizeof(sum));
memset(first,0,sizeof(first));
memset(vis,0,sizeof(vis));
memset(hav,0,sizeof(hav));
e=0;
int cnt=0;
for(int i=1;i<=n;++i){
scanf("%d",&c[i]);
if(!hav[c[i]]){
hav[c[i]]=1;
++cnt;
}
}
for(int i=1;i<n;++i){
scanf("%d%d",&x,&y);
AddEdge(x,y);
AddEdge(y,x);
}
dfs(1);
for (int i=1;i<=n;++i){
if(hav[i]){
ans+=(ll)(n-sum[i])*(ll)(n-sum[i]-1)/2ll;
}
}
printf("Case #%d: %I64d\n",zu,(ll)n*(ll)(n-1ll)/2ll*(ll)cnt-ans);
}
return 0;
}