Codeforces 813C The Tag Game (BFS最短路)
<题目链接>
题目大意:
A、B两人在一颗树上,A在根节点1上,B在节点x上,现在他们轮流走,每次只能走一步,或者不走。A以尽可能靠近B的方式行走,B以尽可能远离A的方式走,B先开始走。问你这两人相遇时,总共走了多少步。
解题分析:
模拟A、B走路的过程可以发现,其实A、B走路的步数就是在B所能够到达的点中,距离A最远的点*2。所谓B能够到达的点就是,B到达这个点的最短时间一定要小于A达到这个点的最短时间。否则B就会在这个点出被A抓住。因为是B先走,所以B只要走那些比A先到的节点,就一定只会和A在距A最远的叶子节点相遇,因为B到了那个叶子节点之后,一定会选择一直不动,所以A、B相遇的时间就如上面所述。
#include <bits/stdc++.h> using namespace std; template<typename T> inline void read(T&x){ x=0;int f=1;char c=getchar(); while(c<'0' || c>'9'){ if(c=='-')f=-1;c=getchar(); } while(c>='0' && c<='9'){ x=x*10+c-'0';c=getchar(); } x*=f; } const int N = 2e5+5; const int INF = 0x3f3f3f3f; int n,x,ans,cnt,loc; int head[N],d1[N],d2[N],vis[N]; struct Edge{ int to,nxt; }e[N<<1]; inline void add(int u,int v){ e[++cnt]=(Edge){v,head[u]}; head[u]=cnt; } void bfs1(int st){ //将根节点到所有点的最短距离全部求出来 memset(d1,0x3f,sizeof(d1)); d1[st]=0; queue<int>q; q.push(st);vis[st]=1; while(q.size()){ int u=q.front();q.pop(); for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(vis[v])continue; d1[v]=d1[u]+1; vis[v]=1; q.push(v); } } } void bfs2(int st){ //将x能够到达的所有点的最短距离求出来 memset(d2,0x3f,sizeof(d2)); memset(vis,0,sizeof(vis)); d2[st]=0;vis[st]=1;ans=d1[st]; queue<int>q;q.push(st); while(q.size()){ int u=q.front();q.pop(); for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(vis[v]||(d2[u]+1)>=d1[v])continue; //如果到达该点的时间晚于1节点到达的时间 d2[v]=d2[u]+1;vis[v]=1; //此时v点B能够到达 ans=max(ans,d1[v]); q.push(v); } } } int main(){ read(n);read(x); for(int i=1;i<n;i++){ int u,v;read(u);read(v); add(u,v);add(v,u); } bfs1(1); /* for(int i=1;i<=n;i++){ printf("i=%d,d1=%d\n",i,d1[i]); } */ bfs2(x); printf("%d\n",2*ans); }

更多精彩