都是求树上(无向)任意两点的最长距离
两题都没有告诉是树,但2631可以根据任意两点之间只存在一条路径和每条路径至多经过一个点一次推出来(否则有环),1985是看了discuss才知道的
做法是先从任意一点开始dfs,找到距离最大的那个点,从这个点开始再进行一次dfs,这时的最大距离则是答案
因为第一次做dfs时,找到的距离最大的那个点,一定是最长路径上的一个端点
如果这个起始点在最长路径上,显然,否则找到的那个点的路径成为新的最长路径的一部分
如果它不在最长路径上,则从起始点开始,沿着最大距离往四周扩散,总有一个点会在最长路径上,这就回到了上面那种情况
还有一种做法是,这两个点肯定是叶子,只要从根开始,找每个节点的子树中到该节点距离最远的两个距离(到某两片叶子的距离),取较大的一对
代码:
2631
#include<iostream> #include<cstdio> #include<memory.h> #include<queue> using namespace std; const int MAX=10005; struct node { int v,w,next; }g[MAX*10]; int adj[MAX],dis[MAX],fa[MAX],ancestor[MAX],ind[MAX],vis[MAX]; int e,ans; void add(int u,int v,int c) { g[e].v=v; g[e].w=c; g[e].next=adj[u]; adj[u]=e++; } /*int find(int x) { if(x!=fa[x]) fa[x]=find(fa[x]); return fa[x]; }*/ int lca(int u,int l) { int i,v,w,a,b,x; a=b=0; dis[u]=l; vis[u]=1; //fa[u]=u; //ancestor[find(u)]=u; for(i=adj[u];i!=-1;i=g[i].next) { v=g[i].v; w=g[i].w; if(vis[v]) continue; x=lca(v,w); if(x>a) { b=a; a=x; } else if(x>b) b=x; } //fa[v]=u; //ancestor[find(u)]=u; //cout<<a<<" "<<b<<" "<<dis[u]<<" "<<endl; ans=max(ans,a+b-2*dis[u]); //cout<<ans<<" "<<u<<" "<<v<<" "<<ancestor[find(u)]<<endl; //cout<<u<<" "<<a<<" "<<b<<endl; return a+l; } int main() { int i,j,w,ma; e=0; ma=-1; memset(adj,-1,sizeof(adj)); memset(dis,0,sizeof(dis)); memset(ind,0,sizeof(ind)); memset(vis,0,sizeof(vis)); while(scanf("%d%d%d",&i,&j,&w)!=EOF) { if(ma<i) ma=i; if(ma<j) ma=j; add(i,j,w); add(j,i,w); //if(w==7) //break; } //for(i=1;i<=ma;i++) //fa[i]=i; for(i=1;i<=ma;i++) if(ind[i]==0) break; //cout<<i<<endl; ans=-1; lca(i,0); cout<<ans<<endl; return 0; }
1985
#include<iostream> #include<cstdio> #include<memory.h> using namespace std; const int MAX=40005; struct node { int v,w,next; }g[MAX*100]; int dis[MAX],adj[MAX]; bool vis[MAX]; int n,m,e; void add(int u,int v,int c) { g[e].v=v; g[e].w=c; g[e].next=adj[u]; adj[u]=e++; } void dfs(int u,int l) { int i; if(dis[u]<l) dis[u]=l; vis[u]=true; for(i=adj[u];i!=-1;i=g[i].next) { if(!vis[g[i].v]) dfs(g[i].v,l+g[i].w); } } int main() { int i,j,l,w,st; char dir[5]; e=0; memset(adj,-1,sizeof(adj)); scanf("%d%d",&n,&m); while(m--) { scanf("%d%d%d%s",&i,&j,&w,&dir); st=i; add(i,j,w); add(j,i,w); } dfs(st,0); for(i=1,l=-1;i<=n;i++) { if(dis[i]>l) { l=dis[i]; st=i; } } memset(dis,0,sizeof(dis)); memset(vis,0,sizeof(vis)); dfs(st,0); for(i=1,l=-1;i<=n;i++) if(dis[i]>l) l=dis[i]; cout<<l<<endl; return 0; }
