題意:n個點n-1條邊;定義集合{A,B,C}若三點能被一條路徑覆蓋則叫作能被簡單路覆蓋;求不被簡單路覆蓋的集合數;ios
正式作的時候咱們隊一直在說,樹形DP,樹形DP。樹形DP! ide
但是三我的都不會= =。。。spa
思路:因爲直接計算狀況較多,可轉化爲算補集,即能被簡單路覆蓋的集合數。code
顯然,假設ABC依次爲路徑上的點,那麼A C必定在以B爲根的不一樣子樹中。blog
那麼咱們就能夠經過枚舉B 爲根,方案數就是s爲B子樹的大小;ip
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <string> 8 #include <vector> 9 #include <queue> 10 #include <cmath> 11 #include <stack> 12 #include <map> 13 #include <cmath> 14 #include <set> 15 #include <climits> 16 #define INF 0x7fffffff 17 #define finc(i,a,b) for(i=a;i<=b;i++) 18 #define fdec(i,a,b) for(i=a;i>=b;i--) 19 #define MAXM 100002 20 #pragma comment(linker, "/STACK:16777216") 21 using namespace std; 22 23 const int MAXN = 100010; 24 struct Edge 25 { 26 int to,next; 27 }edge[MAXN*2]; 28 int head[MAXN],tot; 29 void init() 30 { 31 memset(head,-1,sizeof(head)); 32 tot = 0; 33 } 34 void addedge(int u,int v) 35 { 36 edge[tot].to = v; 37 edge[tot].next = head[u]; 38 head[u] = tot++; 39 } 40 int num[MAXN]; 41 int n; 42 long long ans; 43 void dfs(int u,int pre) 44 { 45 num[u] = 1; 46 int tmp = 0; 47 for(int i = head[u];i!= -1;i = edge[i].next) 48 { 49 int v = edge[i].to; 50 if(v == pre)continue; 51 dfs(v,u); 52 ans += (long long)tmp*num[v]; 53 num[u] += num[v]; 54 tmp += num[v]; 55 } 56 ans += (long long)tmp*(n-num[u]); 57 } 58 59 60 int main() 61 { 62 int u,v; 63 while(scanf("%d",&n) == 1) 64 { 65 init(); 66 for(int i = 1;i < n;i++) 67 { 68 scanf("%d%d",&u,&v); 69 addedge(u,v); 70 addedge(v,u); 71 } 72 ans = 0; 73 dfs(1,-1); 74 long long tot = (long long)n*(n-1)*(n-2)/6; 75 printf("%I64d\n",tot-ans); 76 } 77 return 0; 78 }