标签:target 输入输出 set struct swa main space 前向星 names
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 using namespace std; 8 int n,m,s,tot=0; 9 const int N=500005,M=1000005; 10 int head[N],to[M],nxt[M]; 11 int depth[N],fa[N][22],lg[N]; 12 13 void add(int x,int y) 14 { 15 to[++tot]=y; 16 nxt[tot]=head[x]; 17 head[x]=tot; 18 return ; 19 } 20 21 void dfs(int x,int y) 22 { 23 depth[x]=depth[y]+1; 24 fa[x][0]=y; 25 for(int i=1;(1<<i)<=depth[x];i++) 26 fa[x][i]=fa[fa[x][i-1]][i-1]; 27 for(int i=head[x];i;i=nxt[i]) 28 if(to[i]!=y) 29 dfs(to[i],x); 30 return ; 31 } 32 33 int LCA(int x,int y) 34 { 35 if(depth[x]<depth[y]) 36 swap(x,y); 37 while(depth[x]>depth[y]) 38 x=fa[x][lg[depth[x]-depth[y]]-1]; 39 if(x==y) 40 return x; 41 for(int k=lg[depth[x]];k>=0;--k) 42 if(fa[x][k]!=fa[y][k]) 43 { 44 x=fa[x][k]; 45 y=fa[y][k]; 46 } 47 return fa[x][0]; 48 } 49 50 int main() 51 { 52 cin>>n>>m>>s; 53 for(int i=1;i<n;i++) 54 { 55 int x,y; 56 scanf("%d %d",&x,&y); 57 add(x,y); 58 add(y,x); 59 } 60 dfs(s,0); 61 for(int i=1;i<=n;++i) 62 lg[i]=lg[i-1]+(1<<lg[i-1]==i); 63 for(int i=1;i<=m;++i) 64 { 65 int x,y; 66 scanf("%d %d",&x,&y); 67 printf("%d",LCA(x,y)); 68 } 69 return 0; 70 }
1 #include <iostream> 2 #include <cstdio>//标准输入输出 3 using namespace std; 4 int n,m,s,cnt;//cnt为边计数器 5 int head[500005];//链式前向星 6 int qhead[500005];//链式前向星 (询问) 7 int f[500005];//并查集储存父结点 8 int vis[500005];//判断是否访问过 9 int lca[1000005];//离线存储答案 10 11 struct edge 12 { 13 int nxt; 14 int to; 15 //int dis;边权值默认为 1 16 }e[1000005];//建议4倍 17 18 struct qedge 19 { 20 int nxt; 21 int to; 22 //int dis; 23 }qe[1000005];//建议4倍 24 25 void add(int x,int y/*,int d*/) 26 { 27 e[++cnt].nxt=head[x]; 28 e[cnt].to=y; 29 head[x]=cnt; 30 }//链式前向星加边 31 32 void qadd(int x,int y) 33 { 34 qe[++cnt].nxt=qhead[x]; 35 qe[cnt].to=y; 36 qhead[x]=cnt; 37 }//链式前向星加边 (询问) 38 39 int find(int x) 40 { 41 return f[x]== x ? x : f[x] = find( f[x] );//路径压缩 42 }//“查 ” 43 44 void merge(int a,int b) 45 { 46 int fa=find(a),fb=find(b); 47 if(fa==fb) 48 return ; 49 f[fa]=fb; 50 }//“并 ” 51 52 void setup(int N) 53 { 54 for(int i=1;i<=N;i++) 55 { 56 f[i]=i; 57 } 58 }//初始化 59 60 void tarjan(int x) 61 { 62 cout<<"#访问节点:"<<x<<endl; 63 vis[x]=1;//标记访问 64 for(int i=head[x];i;i=e[i].nxt)//遍历此子节点所有出边 65 { 66 int v=e[i].to; 67 if(!vis[v])//如下一节点未访问 68 { 69 tarjan(v);//继续遍历 70 f[v]=x;//回溯时更新子节点祖先 71 if(v==11) 72 { 73 cout<<"//"<<x<<" "<<f[11]<<endl; 74 } 75 } 76 } 77 for(int i=qhead[x];i;i=qe[i].nxt)//对于询问中有此点的询问组 78 { 79 int qv=qe[i].to; 80 if(vis[qv])//若另一询问节点已被遍历 81 { 82 lca[i]=find(qv);//则对于这组询问,其LCA为另一询问节点最后一次更新的祖先 83 if(i%2)//对于正反两组相同询问 84 lca[i+1]=lca[i];//若为正向的询问,下一组询问为此次询问的反向询问 ,询问结果相同 85 else 86 lca[i-1]=lca[i];//若为反向的询问,下一组询问为此次询问的正向询问 ,询问结果相同 87 } 88 } 89 }//DFS函数 90 91 int main() 92 { 93 cin>>n>>m>>s; 94 for(int i=1;i<n;i++) 95 { 96 int a,b; 97 cin>>a>>b; 98 add(a,b);//无向图正反存边 99 add(b,a); 100 } 101 cnt=0;//懒得再加一个变量qcnt 102 for(int i=1;i<=m;i++) 103 { 104 int a,b; 105 cin>>a>>b; 106 qadd(a,b);//储存正反询问 107 qadd(b,a);//无向图正反存边 108 } 109 setup(n);//初始化 110 tarjan(s);//以s为根开始遍历 111 for(int i=1;i<=m;i++) 112 { 113 printf("%d\n",lca[i*2]);//由于每组询问储存了两遍,所以输出时输出其中一组 114 } 115 return 0; 116 }
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 using namespace std; 5 int n,m,s,cnt,tot; 6 int head[1000005]; 7 int depth[1000005]; 8 int num[1000005]; 9 int rec[2000005][20]; 10 int st[2000005][20]; 11 int euler[1000005]; 12 int dp[1000005];//求节点深度 13 int wd[1000005];//求某一深度树的宽度 14 struct edge 15 { 16 int nxt; 17 int to;边权值 18 }e[1000005];建议开4倍数组 19 20 21 22 void add(int x,int y) 23 { 24 e[++cnt].nxt=head[x]; 25 e[cnt].to=y; 26 head[x]=cnt; 27 } 28 void dfs(int x,int dep) 29 { 30 31 num[x]=++tot; 32 depth[tot]=dep; 33 euler[tot]=x; 34 dp[x]=max(dp[x],depth[tot]); 35 //cout<<"#访问节点:"<<x<<" depth数组:"<<depth[tot]<<endl; 36 for(int i=head[x];i;i=e[i].nxt) 37 { 38 int p=e[i].to; 39 if(num[p]==0) 40 { 41 dfs(p,dep+1); 42 euler[++tot]=x; 43 depth[tot]=dep; 44 } 45 } 46 return ; 47 } 48 49 void RMQ(int N) 50 { 51 for(int j=1;j<=(int)(log((double)N)/log(2.0));j++) 52 { 53 for(int i=1;i<=N;i++) 54 { 55 if(i+(1<<j)-1<=N) 56 if(st[i][j-1]<st[i+(1<<(j-1))][j-1]) 57 st[i][j]=st[i][j-1],rec[i][j]=rec[i][j-1]; 58 else 59 st[i][j]=st[i+(1<<(j-1))][j-1],rec[i][j]=rec[i+(1<<(j-1))][j-1]; 60 } 61 } 62 } 63 64 int search(int l,int r) 65 { 66 int k=(int)(log((double)(r-l+1))/log(2.0)); 67 if(st[l][k]<st[r-(1<<k)+1][k]) 68 return rec[l][k]; 69 else 70 return rec[r-(1<<k)+1][k]; 71 } 72 73 74 75 int main() 76 { 77 cin>>n>>m; 78 for(int i=1;i<=n-1;i++) 79 { 80 int a,b; 81 scanf("%d %d",&a,&b); 82 add(a,b); 83 add(b,a); 84 } 85 dfs(1,1); 86 for(int i=1;i<=tot;i++) 87 { 88 st[i][0]=depth[i],rec[i][0]=euler[i]; 89 } 90 RMQ(tot); 91 /* 92 int dcnt=0,maxx=0; 93 for(int i=1;i<=n;i++) 94 { 95 wd[dp[i]]++; 96 } 97 for(int i=1;i<=n;i++) 98 { 99 if(wd[i]==0) 100 { 101 break; 102 } 103 dcnt++; 104 } 105 for(int i=1;i<=wcnt+1;i++) 106 { 107 maxx=max(maxx,wd[i]); 108 } 109 //求树深度dcnt/宽度 maxx 110 */ 111 for(int i=1;i<=m;i++) 112 { 113 int l,r,fg=0; 114 scanf("%d %d",&l,&r); 115 if(num[l]>num[r]) 116 { 117 swap(num[l],num[r]); 118 fg=1; 119 } 120 printf("%d\n",search(num[l],num[r])); 121 if(fg==1) 122 swap(num[l],num[r]); 123 } 124 return 0; 125 }
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 int n,m,s,cnt; 5 int head[500005]; 6 int son[500005]; 7 int depth[500005]; 8 int f[500005]; 9 int top[500005]; 10 struct edge 11 { 12 int nxt; 13 int to; 14 //int dis; 15 }e[2000005]; 16 void add(int x,int y/*,int d*/) 17 { 18 e[++cnt].nxt=head[x]; 19 e[cnt].to=y; 20 head[x]=cnt; 21 } 22 void dfs(int x) 23 { 24 son[x]=1; 25 depth[x]=depth[f[x]]+1; 26 for(int i=head[x];i;i=e[i].nxt) 27 { 28 int p=e[i].to; 29 if(f[x]!=p) 30 { 31 f[p]=x; 32 dfs(p); 33 son[x]+=son[p]; 34 } 35 } 36 } 37 void dsf(int x) 38 { 39 int t=0; 40 if(!top[x]) 41 top[x]=x; 42 for(int i=head[x];i;i=e[i].nxt) 43 { 44 int p=e[i].to; 45 if(p!=f[x]&&son[p]>son[t]) 46 t=p; 47 } 48 if(t) 49 { 50 top[t]=top[x]; 51 dsf(t); 52 } 53 for(int i=head[x];i;i=e[i].nxt) 54 { 55 int p=e[i].to; 56 if(p!=f[x]&&t!=p) 57 dsf(p); 58 } 59 } 60 int search(int x,int y) 61 { 62 for(;top[x]!=top[y];) 63 { 64 if(depth[top[x]]<depth[top[y]]) 65 { 66 swap(x,y); 67 } 68 x=f[top[x]]; 69 } 70 if(depth[x]>depth[y]) 71 { 72 swap(x,y); 73 } 74 return x; 75 } 76 77 void setup(int x) 78 { 79 for(int i=1;i<=x;i++) 80 { 81 f[x]=x; 82 } 83 } 84 85 int main() 86 { 87 cin>>n>>m>>s; 88 for(int i=1;i<=n-1;i++) 89 { 90 int a,b; 91 scanf("%d%d",&a,&b); 92 add(a,b); 93 add(b,a); 94 } 95 setup(n); 96 dfs(s); 97 dsf(s); 98 for(int i=1;i<=m;i++) 99 { 100 int a,b; 101 scanf("%d %d",&a,&b); 102 printf("%d\n",search(a,b)); 103 } 104 return 0; 105 }
原文地址:
-----2021届张若琛
标签:target 输入输出 set struct swa main space 前向星 names
原文地址:https://www.cnblogs.com/btjzoi/p/11722792.html