2020牛客NOIP赛前集训营-提高组(第三场)C-牛半仙的妹子Tree【虚树,最短路】
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                2020牛客NOIP赛前集训营-提高组(第三场)C-牛半仙的妹子Tree【虚树,最短路】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                正題
題目鏈接:https://ac.nowcoder.com/acm/contest/7609/C
題目大意
給出nnn個點的一棵樹,mmm個時刻各有一個操作
解題思路
考慮沒有二操作怎么搞,可以理解為標記代表起點,然后跑一遍最短路求出每個點被標記的最短時間。
如果有二操作的話是不是就很麻煩了,因為它像一個分割符一樣切開兩段操作。
那么就直接分開操作就好了!對于每段操作的所有點建立虛樹,然后跑最短路就好了。
時間復雜度O(nlog?n)O(n\log n)O(nlogn),因為是樹就用我們的老朋友SPFA\text{SPFA}SPFA就好了
正解是定期重構+SPFA\text{SPFA}SPFA的,懶得寫
code
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define mp(x,y) make_pair(x,y) using namespace std; const int N=2e5+10,T=18; struct node{int to,next,w; }a[N<<1]; int n,m,cnt,qnt,pnt,tot,top,ls[N]; int dep[N],dfn[N],f[N][T+1],s[N]; int ve[N],dis[N],t[N],p[N]; pair<int,int> q[N];bool v[N]; void addl(int x,int y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return; } void adde(int x,int y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=dep[y]-dep[x];a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;a[tot].w=dep[y]-dep[x];ve[++pnt]=x;ve[++pnt]=y;return; } void dfs(int x,int fa){dep[x]=dep[fa]+1;dfn[x]=++cnt;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa)continue;f[y][0]=x;dfs(y,x);}return; } int LCA(int x,int y){if(dep[x]>dep[y])swap(x,y);for(int i=T;i>=0;i--)if(dep[f[y][i]]>=dep[x])y=f[y][i];if(x==y)return x;for(int i=T;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];return f[x][0]; } bool cmp(int x,int y) {return dfn[x]<dfn[y];} void Ins(int x){if(!top){s[++top]=x;return;}int lca=LCA(x,s[top]);while(top>1&&dep[s[top-1]]>dep[lca])adde(s[top-1],s[top]),top--;if(dep[s[top]]>dep[lca])adde(lca,s[top]),top--;if(s[top]!=lca||!top)s[++top]=lca;s[++top]=x;return; } void solve(){queue<int> q;sort(ve+1,ve+1+pnt);pnt=unique(ve+1,ve+1+pnt)-ve-1;for(int i=1;i<=pnt;i++){int x=ve[i];if(t[x])q.push(x),v[x]=1,dis[x]=t[x];}while(!q.empty()){int x=q.front();v[x]=0;q.pop();for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(dis[x]+a[i].w<dis[y]){dis[y]=dis[x]+a[i].w;if(!v[y])q.push(y),v[y]=1;}}}return; } int main() {scanf("%d%d",&n,&m);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);addl(x,y);addl(y,x);}dfs(1,1);for(int j=1;j<=T;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];cnt=tot=0;m++;memset(ls,0,sizeof(ls));memset(dis,0x3f,sizeof(dis));for(int z=1;z<=m;z++){int op,x;if(z==m)op=2;else scanf("%d%d",&op,&x);if(op==1){if(!t[x])p[++cnt]=x,t[x]=z;}else if(op==3)q[++qnt]=mp(x,z),p[++cnt]=x;else{sort(p+1,p+1+cnt,cmp);cnt=unique(p+1,p+1+cnt)-p-1;if(p[1]!=1)s[++top]=1;for(int i=1;i<=cnt;i++)Ins(p[i]);while(top>1)adde(s[top-1],s[top]),top--;solve();for(int i=1;i<=qnt;i++){if(dis[q[i].first]<=q[i].second)puts("wrxcsd");else puts("orzFsYo");}for(int i=1;i<=cnt;i++){int x=p[i];ls[x]=t[x]=0;dis[x]=1e9;}for(int i=1;i<=pnt;i++){int x=ve[i];ls[x]=t[x]=0;dis[x]=1e9;}cnt=qnt=top=tot=pnt=0;}}return 0; }總結
以上是生活随笔為你收集整理的2020牛客NOIP赛前集训营-提高组(第三场)C-牛半仙的妹子Tree【虚树,最短路】的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 怎么设置微信支付(怎么设置微信支付顺序)
- 下一篇: 空间主页怎么制作(空间主页怎么制作视频)
