树上最短路
题目:
给出一棵树进行如下操作:
(1)把某个点上染黑
(2)询问某个点,到最近黑点的距离。
开始时,把‘1’点染黑。
• 10% N,M ≤ 10
• 40% N,M ≤ 100
• 100% N ≤ 2 × 10 5 ,M ≤ 10 5
思路:(搜索的思路)
每加入一个点就更新,最短路。记录答案。
一个剪枝:
当你要更新的值大于或等于它原来的值时,就不用向后更新了。(因为后面的点肯定离另一个点比这个点近)
具体代码:
bfs
#include<iostream> #include<cstdio> #include<math.h> #include<queue> #include<algorithm> #include<cstring> using namespace std; int n,m,q[99999999]; int h[200009],next[400009],to[400009],cnt,ans[200009]; void bfs(int x) { int l=0,r=1; int now,t; q[x]=x;ans[x]=1; while(l<=r) { now=q[++l]; for(int i=h[x];i;i=next[i]) { t=to[i]; if(ans[now]+1<ans[t]) { ans[t]=ans[now]+1; q[++r]=t; } } } } int main() { freopen("travel.in","r",stdin); freopen("travel.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1,x,y;i<n;i++) { scanf("%d%d",&x,&y); to[++cnt]=y,next[cnt]=h[x],h[x]=cnt; to[++cnt]=x,next[cnt]=h[y],h[y]=cnt; } memset(ans,0x7f,sizeof(ans)); bfs(1); for(int i=1,A,B;i<=m;i++) { scanf("%d",&A); if(A==2) { scanf("%d",&B); printf("%d\n",ans[B]); } if(A==1) { scanf("%d",&B); bfs(B); } } return 0; }
dfs
#include<iostream> #include<cstdio> #include<math.h> #include<queue> #include<algorithm> #include<cstring> using namespace std; int n,m; int h[200009],next[400009],to[400009],cnt,ans[200009],last; void dfs(int x,int last,int y) { ans[x]=y; int t; for(int i=h[x];i;i=next[i]) { t=to[i]; if(t!=last&&y+1<ans[t]) dfs(t,x,y+1); } return; } int main() { freopen("cicada.in","r",stdin); freopen("cicada.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1,x,y;i<n;i++) { scanf("%d%d",&x,&y); to[++cnt]=y,next[cnt]=h[x],h[x]=cnt; to[++cnt]=x,next[cnt]=h[y],h[y]=cnt; } memset(ans,0x7f,sizeof(ans)); dfs(1,1,0); for(int i=1,A,B;i<=m;i++) { scanf("%d",&A); if(A==2) { scanf("%d",&B); printf("%d\n",ans[B]); } if(A==1) { scanf("%d",&B); dfs(B,B,0); } } return 0; }