樹形dp求樹直徑、兩次dfs求樹直徑
阿新 • • 發佈:2018-12-21
樹形dp求樹直徑:
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include<algorithm> #include <set> #include <queue> #include <stack> #include<vector> #include<map> #include<ctime> #define ll long long using namespace std; const int N=100010,M=1000010; int head[N]; int ver[M]; int edge[M]; int Next[M]; bool v[N]; int tot; void add(int x,int y,int z) { ver[++tot]=y; edge[tot]=z; Next[tot]=head[x]; head[x]=tot; } ll ans; int d[N];//以N為根節點在其子樹的最長路 void dp(int x)//根節點 { v[x]=1; for(int i=head[x];i;i=Next[i]) { int y=ver[i]; if(v[y])continue; dp(y); if(d[x]+d[y]+edge[i]>ans)ans=d[x]+d[y]+edge[i];//這兩個if的順序不要弄錯 if(d[y]+edge[i]>d[x])d[x]=d[y]+edge[i];// } } int main() { int n;//節點數 int m;//邊數 while(cin>>n>>m) { ans=-9999999999; for(int i=1;i<=m;++i) { int x,y,z; cin>>x>>y>>z; add(x,y,z); add(y,x,z); } dp(1); cout<<ans<<endl; } }
兩次dfs求樹直徑:
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include<algorithm> #include <set> #include <queue> #include <stack> #include<vector> #include<map> #include<ctime> #define ll long long using namespace std; const int N=100010,M=1000010; int head[N]; int ver[M]; int edge[M]; int Next[M]; int tot; priority_queue< pair<int,int> >Q; void add(int x,int y,int z) { ver[++tot]=y; edge[tot]=z; Next[tot]=head[x]; head[x]=tot; } ll ans;//記錄最深的點的節點標號; int d[N];//以N為根節點的子樹的深度; bool v[N];//無向圖防止子節點回到父節點 void dfs(int x) { v[x]=1; for(int i=head[x];i;i=Next[i]) { int y=ver[i]; if(v[y])continue; d[y]=d[x]+1;//從上往下加一即可; if(d[y]>d[ans])ans=y; dfs(y); } } int main() { int n;//節點數 int m;//邊數 while(cin>>n>>m) { ans=0; d[0]=0; for(int i=1;i<=m;++i) { int x,y,z; cin>>x>>y>>z; add(x,y,z); add(y,x,z); } dfs(1); memset(d,0,sizeof(d));//兩次dfs注意清空搜尋標記陣列、子樹深度陣列d; memset(v,0,sizeof(v)); //cout<<ans<<endl; dfs(ans); cout<<d[ans]<<endl;//最後答案儲存在d中,答案點標號為ans; } return 0; }