HDU 4705 Y

Y

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)


Problem Description
 
Sample Input
4 1 2 1 3 1 4
 
Sample Output
1
Hint
1. The only set is {2,3,4}. 2. Please use #pragma comment(linker, "/STACK:16777216")
 
Source
    思路:反面考虑,用总的方案数减去A,B,C三点在同一路径上的方案数。
            确定中间点B,在当前以B为根求得的son中任选一个,在剩下的节点n-all_son-1(all_son为已经求得的B的儿子的个数)中任选一个,构成son*(n-all_son-1)种组合。
            另外,手动扩栈(递归的层数太大,以至于爆栈,就需要把栈扩大些),C++提交。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <algorithm>
#include <vector>
#include <stack>
#include <math.h>
#include <stdlib.h>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL ;
const int size=100008 ;
int vec[size] ;
bool visited[size] ;
struct Me{
    struct Edge{
       int v ;
       int next ;
    };
    LL N ;
    int id ;
    LL sum ;
    Edge edge[2*size] ;
    Me(){} ;
    Me(int n):N(n){
       id=0 ;
       sum=0 ;
       memset(vec,-1,sizeof(vec)) ;
       memset(visited,0,sizeof(visited)) ;
    }
    void add_edge(int u ,int v){
         edge[id].v=v ;
         edge[id].next=vec[u] ;
         vec[u]=id++ ;
    }
    LL dfs(int u){
        visited[u]=1 ;
        LL all_son=0 ;
        for(int e=vec[u];e!=-1;e=edge[e].next){
            int v=edge[e].v ;
            if(visited[v])
                continue ;
            LL son=dfs(v) ;
            all_son+=son ;
            sum+=(N-all_son-1)*son ;
        }
        return all_son+1 ;
    }
    LL gao(){
       int u ,v ;
       for(int i=1;i<N;i++){
           scanf("%d%d",&u,&v) ;
           add_edge(u,v) ;
           add_edge(v,u) ;
       }
       dfs(1) ;
       return N*(N-1)*(N-2)/6-sum ;
    }
};
int main(){
   LL n ;
   while(cin>>n){
      Me me(n);
      cout<<me.gao()<<endl ;
   }
   return 0 ;
}

  

 
原文地址:https://www.cnblogs.com/liyangtianmen/p/3302507.html