1. 程式人生 > >NOIP 提高組 2014 聯合權值(圖論???)

NOIP 提高組 2014 聯合權值(圖論???)

傳送門

https://www.cnblogs.com/violet-acmer/p/9937201.html

 

題解:

  相關變數解釋:

int n;
int fa[maxn];//fa[i] : i的父親節點
int w[maxn];//w[i] : i的權值
long long sum[maxn];//sum[i] : i節點的所有兒子節點的權值和
int maxSon1[maxn];//maxSon1[i] : i節點的所有兒子中權值最大值(如果有超過兩個兒子)
int maxSon2[maxn];//maxSon2[i] : i節點的所有兒子中權值第二大值(如果有超過兩個兒子)
vector<int
>G[maxn];//存邊 vector<int >son[maxn];//son[i] : 記錄節點 i 的所有兒子節點

  步驟:

  (1):先Dfs(u,f)預處理出節點u的父親節點fa[u],兒子節點son[u],兒子節點的權值和sum[u],以及兒子節點的權值最大的前兩個權值maxSon1[u],maxSon2[u];

  (2):如果某節點 i 含有兩個及以上兒子,則每兩個兒子間也可構成長度為 2 的邊長,求出節點 i 的兒子節點的聯合權值,並判斷是否可以更新聯合權值的最大值;

  (3):求 i 節點與其父親的父親節點 j 構成的聯合權值,並將其二倍(i 與 j 構成聯合權值,同樣 j 與 i 也可以構成聯合權值,所以需要加入兩個)與加入到聯合權值之和

       中,並判斷是否可以更新聯合權值的最大值。

AC程式碼:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define pb(x) push_back(x)
 4 #define mem(a,b) memset(a,b,sizeof(a))
 5 const int maxn=200000+10;
 6 const int MOD=10007;
 7 
 8 int n;
 9 int fa[maxn];
10 int w[maxn];
11 long long sum[maxn];
12 int maxSon1[maxn]; 13 int maxSon2[maxn]; 14 vector<int >G[maxn]; 15 vector<int >son[maxn]; 16 void addEdge(int u,int v) 17 { 18 G[u].pb(v); 19 G[v].pb(u); 20 } 21 void Dfs(int u,int f) 22 { 23 fa[u]=f; 24 for(int i=0;i < G[u].size();++i) 25 { 26 int to=G[u][i]; 27 if(to != f) 28 { 29 son[u].pb(to); 30 sum[u] += w[to]; 31 if(w[to] > maxSon1[u]) 32 { 33 if(maxSon1[u] > maxSon2[u]) 34 maxSon2[u]=maxSon1[u]; 35 maxSon1[u]=w[to]; 36 } 37 else if(w[to] > maxSon2[u]) 38 maxSon2[u]=w[to]; 39 Dfs(to,u); 40 } 41 } 42 } 43 44 void Solve() 45 { 46 mem(sum,0); 47 mem(maxSon1,0); 48 mem(maxSon2,0); 49 Dfs(1,-1); 50 int maxRes=0; 51 int res=0; 52 for(int i=1;i <= n;++i)//步驟(2) 53 { 54 if(son[i].size() >= 2) 55 { 56 maxRes=max(maxRes,maxSon1[i]*maxSon2[i]); 57 for(int j=0;j < son[i].size();++j) 58 res=res%MOD+((sum[i]-w[son[i][j]])%MOD)*(w[son[i][j]]%MOD); 59 } 60 } 61 for(int i=2;i <= n;++i)//步驟(1) 62 { 63 if(fa[i] != 1) 64 { 65 maxRes=max(maxRes,w[fa[fa[i]]]*w[i]); 66 res=res%MOD+2*w[fa[fa[i]]]*w[i]; 67 } 68 } 69 printf("%d %d\n",maxRes,res%MOD); 70 } 71 int main() 72 { 73 scanf("%d",&n); 74 for(int i=1;i < n;++i) 75 { 76 int u,v; 77 scanf("%d%d",&u,&v); 78 addEdge(u,v); 79 } 80 for(int i=1;i <= n;++i) 81 scanf("%d",w+i); 82 Solve(); 83 }
View Code

  坑:  

    步驟(2)的情況剛開始忘了,然後,吃了一發wa.................