1. 程式人生 > >codeforces 842C dp

codeforces 842C dp

題目大意:給你一棵樹,樹上的每一個節點有一個值,定義一個節點的美麗值為這個節點到根節點的的路徑上的每一個個節點(包括自己)的所有的值的最大公約數,現在給定一種操作,對於某一個點的美麗值現在可以把路徑上的任意一個點的值變為0,(規定GCD(x,0)=x)問對於每一個個點單獨考慮,輸出每一個點的美麗值的最大值。

思路:在大佬的幫助下明白了dp的思路,定義dp[i][0]表示從根節點到i已經有一個被改變為0的所有可能產生的公約數的集合,dp[i][1]表示從根節點到i沒有節點被變為0的所有可能的公約數的集合,這裡公約數的集合只可能是logn的級別,具體的原因我還不是很清楚。
那麼很明顯dp應該這樣定義s

et<int>dp[N][2]
轉移很簡單,這裡就不寫了,直接看程式碼

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cstring>
#define clr(x) memset(x,0,sizeof(x))
using namespace std; #define LL long long int dat[200005]; vector<int>vec[200005]; int ans[200005]; bool vis[200005]; set<int>dp[200005][2]; int gcd(int a,int b) { if(a==0||b==0)return max(a,b); return a%b==0?b:gcd(b,a%b); } void dfs(int now,int ma) { for(set<int>::iterator it = dp[now][0].begin();it!=dp[now][0
].end();it++) { ans[now] = max(ans[now],*it); } for(set<int>::iterator it = dp[now][1].begin();it!=dp[now][1].end();it++) { ans[now] = max(ans[now],*it); } vis[now] = true; for(int i = 0;i<vec[now].size();i++) { if(vis[vec[now][i]])continue; for(set<int>::iterator it = dp[now][1].begin();it!=dp[now][1].end();it++) { int temp = gcd(*it,dat[vec[now][i]]); //cout << "k" << temp <<" " << *it <<vec[]<< endl; dp[vec[now][i]][0].insert(*it); dp[vec[now][i]][1].insert(temp); } for(set<int>::iterator it = dp[now][0].begin();it!=dp[now][0].end();it++) { int temp = gcd(*it,dat[vec[now][i]]); dp[vec[now][i]][0].insert(temp); //dp[vec[now][i]][1].insert(temp); } dfs(vec[now][i],ans[now]); } } int main() { int n; while(scanf("%d",&n)!=EOF) { clr(vis); clr(ans); for(int i = 0;i<=n;i++) vec[i].clear(),dp[i][0].clear(),dp[i][1].clear(); for(int i = 1;i<=n;i++) scanf("%d",&dat[i]); for(int i = 0;i<n-1;i++) { int a,b; scanf("%d%d",&a,&b); vec[a].push_back(b); vec[b].push_back(a); } dp[1][1].insert(dat[1]); dp[1][0].insert(0); dfs(1,0); //for(set<int>::iterator it = dp[2][0].begin();it!=dp[2][0].end();it++)cout << *it <<" ";cout << endl; for(int i = 1;i<=n;i++) { if(i!=1)printf(" "); printf("%d",ans[i]); }printf("\n"); } return 0; }