【tyvj1520】樹的直徑(dfs||樹形dp)
阿新 • • 發佈:2019-01-30
題目:
題解:
題目給了一種dfs的做法,但是有負邊權的時候不能用
還有一種dp的做法:f[i]g[i]分別表示i點到它的子樹中的點距離的最大值和次大值,答案就是max(f[i]+g[i])哎為什麼不會加重呢?因為每一條邊只遍歷一遍,如果是鏈狀則只有f[i]的值沒有g[i]的值
程式碼:
dfs:
#include <cstdio> #define N 50000 using namespace std; int tot,nxt[N],point[N],v[N],c[N],ans,ansp; void addline(int x,int y,int cap) { ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=cap; ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; c[tot]=cap; } void dfs(int x,int fa,int dis) { if (dis>ans) ans=dis,ansp=x; for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa) dfs(v[i],x,dis+c[i]); } void askans(int x,int fa,int dis) { if (dis>ans) ans=dis; for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa) dfs(v[i],x,dis+c[i]); } int main() { int n,i; scanf("%d",&n); for (i=1;i<n;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); addline(a,b,c); } ans=0; ansp=1; dfs(1,0,0); ans=0; askans(ansp,0,0); printf("%d",ans); }
dp:
#include <cstdio> #include <iostream> #define N 50000 using namespace std; int tot,nxt[N],point[N],v[N],c[N],ans,f[N],g[N],n,i; void addline(int x,int y,int cc) { ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=cc; ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; c[tot]=cc; } void treedp(int x,int fa) { for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa) { treedp(v[i],x); if (f[v[i]]+c[i]>f[x]) { g[x]=f[x]; f[x]=f[v[i]]+c[i]; } else g[x]=max(g[x],f[v[i]]+c[i]); } ans=max(ans,f[x]+g[x]); } int main() { scanf("%d",&n); for (i=1;i<n;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); addline(a,b,c); } treedp(1,0); printf("%d",ans); }