2018-2019 ACM-ICPC Brazil Subregional Programming Contest L. Subway Lines
作者:互联网
下午小细节没处理好,然后WA了。晚上静心改了改就好了。开心!
不过.....499ms?
在网上搬了找重心的dfs代码。
得找lca,但是我已经忘了该用什么算法,因为很久之前看的找lca的题/算法,但是太久没用,忘了.... 所以...就没用什么算法模板了。
从重心G开始遍历,然后就,记录父亲。
会超时。其实有这个想法,但是一开始打算碰碰运气..结果真的超时。
所以要优化。 当节点的度数为2且父亲的度数为2时,可以将当前节点合并到父亲节点,这样子不断合并,就可以避免链式的n^2超时。
既然要合并,就用一个数组记录一个点的真正价值,初始化都为1,合并的点的价值就加起来。
然后就不会超时了。然后我就WA了。因为我忘记在合并的时候更改深度。
晚上想起来了,就过了。
嘻嘻。
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<queue> #define debug printf("!"); using namespace std; typedef __int64 ll;//%I64d const int mod=1e9+7; const int maxn=1e5+50; const int inf=0x3f3f3f3f; vector<int>p[maxn]; int fath[maxn]={0},dep[maxn]={0}; int son[maxn]={0},G,bal,n,val[maxn]; void dfs(int v,int fa) { son[v]=0; int pbal=0,i,j,k; for(i=0;i<p[v].size();i++) { k=p[v][i]; if(k!=fa) { dfs(k,v); son[v]+=son[k]+1; pbal=max(pbal,son[k]+1); } } pbal=max(pbal,n-son[v]-1); if(pbal<bal||(pbal==bal&&v<G)) { G=v; bal=pbal; } } void gettree() { int now,k,kk; int vis[maxn]={0}; queue<int> que; que.push(G);fath[G]=G;vis[G]=1,dep[G]=0; while(!que.empty()) { now=que.front();que.pop();k=p[now].size();kk=p[fath[now]].size(); for(int i=0;i<k;i++) { if(vis[p[now][i]])continue; vis[p[now][i]]=1; fath[p[now][i]]=now; if(k==2&&kk==2&&now!=G)fath[p[now][i]]=fath[now]; dep[p[now][i]]=dep[fath[p[now][i]]]+1; que.push(p[now][i]); } if(k==2&&kk==2&&now!=G)val[fath[now]]+=val[now]; } } int solve(int a,int b,int &fa,int viss[]) { int ans=0; if(viss[a])ans+=val[a]; else viss[a]=1; if(a!=b) { if(viss[b])ans+=val[b]; else viss[b]=1; } while(dep[a]>dep[b]) { a=fath[a]; if(viss[a])ans+=val[a]; else viss[a]=1; } while(dep[b]>dep[a]) { b=fath[b]; if(viss[b])ans+=val[b]; else viss[b]=1; } while(a!=b) { a=fath[a]; if(viss[a])ans+=val[a]; else viss[a]=1; if(a==b)break; b=fath[b]; if(a==b)break; if(viss[b])ans+=val[b]; else viss[b]=1; } fa=a; return ans; } int main() { int q,i,j,k,s,e,a,b,ans,c,d,fa1,fa2; scanf("%d%d",&n,&q); for(i=1;i<n;i++) { val[i]=1; scanf("%d%d",&s,&e); p[s].push_back(e); p[e].push_back(s); }val[n]=1; G=0;bal=inf; dfs(1,-1); // printf("##G:%d\n",G); gettree(); while(q--) { int viss[maxn]={0}; scanf("%d%d%d%d",&a,&b,&c,&d); solve(a,b,fa1,viss); ans=solve(c,d,fa2,viss); printf("%d\n",ans); } }
标签:Brazil,viss,Contest,int,fath,Lines,maxn,ans,include 来源: https://www.cnblogs.com/kkkek/p/11514835.html