CF #328div2 D
这题不难,当时想出来了,可是却写不出来~~
现在慢慢写回来,也写得好挫~
可以知道,被攻击的城市必定可以组成一棵树,然后,传送到的点必定也是城市之一。如果出发后回到原点,则需要2E,E是树的边数,则2E-D就是答案,D是树中直径。
我写得好锉~
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> #define LL long long using namespace std; const int MAX=123460; struct Edge{ int u,v,next; }edge[MAX*2]; int head[MAX],dis[MAX]; int n,m,tot; bool chose[MAX]; int pre[MAX],point[MAX],deg[MAX]; int dis1[MAX],node1[MAX],dis2[MAX],node2[MAX]; bool vis[MAX]; void addedge(int u,int v){ edge[tot].u=u; edge[tot].v=v; edge[tot].next=head[u]; head[u]=tot++; } int BFS(int rt,int counts){ queue<int>que; que.push(rt); vis[rt]=true; int u,v; while(!que.empty()&&counts){ u=que.front(); que.pop(); vis[u]=true; if(chose[u]) counts--; for(int e=head[u];e!=-1;e=edge[e].next){ v=edge[e].v; if(vis[v]) continue; que.push(v); pre[v]=u; } } memset(vis,false,sizeof(vis)); while(!que.empty()) que.pop(); for(int i=1;i<=m;i++) que.push(point[i]); while(!que.empty()){ u=que.front(); que.pop(); v=pre[u]; if(v!=-1){ if(!vis[v]){ que.push(v); chose[v]=false; } vis[v]=true; } } while(!que.empty()) que.pop(); memset(vis,false,sizeof(vis)); for(int i=1;i<=m;i++) if(chose[point[i]]) que.push(point[i]); memset(deg,0,sizeof(deg)); int ans=0; while(!que.empty()){ u=que.front(); vis[u]=true; que.pop(); v=pre[u]; if(v!=-1){ ans++; if(!vis[v]) que.push(v); deg[v]++; vis[v]=true; } } while(!que.empty()) que.pop(); for(int i=1;i<=m;i++) if(chose[point[i]]) que.push(point[i]); while(!que.empty()){ u=que.front(); dis[dis1[u]]=dis[dis1[u]]==0?min(node1[u],u):min(min(node1[u],u),dis[dis1[u]]); dis[dis1[u]+dis2[u]]=dis[dis1[u]+dis2[u]]==0?min(node1[u],node2[u]):min(min(node1[u],node2[u]),dis[dis1[u]+dis2[u]]); que.pop(); v=pre[u]; if(v!=-1){ deg[v]--; if(!deg[v]) que.push(v); dis1[u]+=1; if(dis1[u]>dis1[v]){ dis2[v]=dis1[v],node2[v]=node1[v]; dis1[v]=dis1[u],node1[v]=node1[u]; } else if(dis1[u]==dis1[v]){ if(node1[u]<node1[v]){ dis2[v]=dis1[v],node2[v]=node1[v]; node1[v]=node1[u]; } else{ if(dis1[u]>dis2[v]){ dis2[v]=dis1[u],node2[v]=node1[u]; } else if(dis1[u]==dis2[v]){ if(node1[u]<node2[v]){ node2[v]=node1[u]; } } } } else{ if(dis1[u]>dis2[v]){ dis2[v]=dis1[u],node2[v]=node1[u]; } else if(dis1[u]==dis2[v]){ if(node1[u]<node2[v]){ node2[v]=node1[u]; } } } } } /// cout<<ans<<endl; /// printf("%d\n",node1[rt]); for(int i=n;i>=1;i--){ if(dis[i]>0){ printf("%d\n",dis[i]); return ans*2-i; } } printf("%d\n",point[1]); return ans; } int main(){ int u,v; while(scanf("%d%d",&n,&m)!=EOF){ for(int i=1;i<=n;i++){ head[i]=-1,chose[i]=false,pre[i]=-1; dis1[i]=dis2[i]=0,node1[i]=node2[i]=i; vis[i]=false; dis[i]=0; } tot=0; for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } for(int i=1;i<=m;i++){ scanf("%d",&u); point[i]=u; chose[u]=true; } printf("%d\n",BFS(u,m)); } return 0; }