标签:log eof 计算 bsp code std printf efi bre
一道例题:
最近公共祖先
Description
5 3
2 3
3 4
3 1
1 5
3 5
4 5
1 2
#include<iostream> #include<algorithm> #include<cmath> #include<cstring> using namespace std; int n,m,cnt=0; struct node1{int to,next;}a[200005]; int h[200005],prt[200005],f[200005][25],d[200005]; void add(int x,int y){cnt++;a[cnt].to=y;a[cnt].next=h[x];h[x]=cnt;} void dfs(int x,int deep) { d[x]=deep; int i; for(i=h[x];i;i=a[i].next) dfs(a[i].to,deep+1); } void ST() { memset(f,-1,sizeof(f)); int i,j; for(i=1;i<=n;i++)f[i][0]=prt[i]; for(j=1;(1<<j)<=n;j++) for(i=1;i<=n;i++) if(f[i][j-1]!=-1)f[i][j]=f[f[i][j-1]][j-1]; } int LCA(int x,int y) { int i,j,k; if(d[x]<d[y])swap(x,y); k=int(log(d[x])/log(2)); for(i=k;i>=0;i--) if(d[x]-(1<<i)>=d[y])x=f[x][i]; if(x==y)return y; for(i=k;i>=0;i--) if(f[x][i]!=-1&&f[x][i]!=f[y][i]){x=f[x][i];y=f[y][i];} return f[x][0]; } int main() { int x,y,i,j,root; cin>>n>>m; for(i=1;i<=n-1;i++) { scanf("%d%d",&x,&y); add(x,y); prt[y]=x; } root=1; while(prt[root]!=0)root=prt[root]; dfs(root,1); ST(); for(i=1;i<=m;i++) { scanf("%d%d",&x,&y); printf("%d\n",LCA(x,y)); } return 0; }
二.tarjan求法
#include<iostream> #include<queue> #include<cstdio> #include<cstring> #define ll long long using namespace std; int n,m,d[200005],prt[200005],cnt,son[200005],size[200005],tot,h[200005],top[200005]; struct node{int to,next;}a[200005]; void add(int x,int y){cnt++;a[cnt].to=y;a[cnt].next=h[x];h[x]=cnt;} void dfs1(int x,int fa,int deep) { int i,j,maxsize=0; d[x]=deep; size[x]=1; for(i=h[x];i;i=a[i].next) { j=a[i].to; dfs1(j,x,deep+1); if(size[j]>maxsize)maxsize=size[j],son[x]=j; size[x]+=size[j]; } } void dfs2(int x,int anc) { int i,j; top[x]=anc; if(son[x]!=-1)dfs2(son[x],anc); for(i=h[x];i;i=a[i].next) { j=a[i].to; if(j==son[x])continue; dfs2(j,j); } } int ask(int x,int y) { int f1=top[x],f2=top[y]; while(f1!=f2) { if(d[f1]<d[f2])swap(f1,f2),swap(x,y); x=prt[f1];f1=top[x]; } if(x==y)return x; if(d[x]>d[y])swap(x,y); return x; } int main() { int i,j,k,x,y,root; scanf("%d%d",&n,&m); for(i=2;i<=n;i++)scanf("%d%d",&x,&y),add(x,y),prt[y]=x; for(i=1;i<=n;i++)if(!prt[i]){root=i;break;} memset(son,-1,sizeof(son)); dfs1(root,0,1); dfs2(root,root); for(i=1;i<=m;i++) { scanf("%d%d",&x,&y); printf("%d\n",ask(x,y)); } return 0; }
三.欧拉序求法
#include<iostream> #include<queue> #include<cstdio> #include<cmath> #define ll long long using namespace std; int n,m,d[200005],prt[200005],cnt,tot,h[200005]; struct node{int to,next;}a[200005]; void add(int x,int y){cnt++;a[cnt].to=y;a[cnt].next=h[x];h[x]=cnt;} int f[400005][20],g[400005][20]; int q[400005]; int td1[200005],td2[200005]; void dfs(int x,int deep) { int i,j; d[x]=deep; q[++tot]=x; td1[x]=tot;td2[x]=tot; for(i=h[x];i;i=a[i].next) { j=a[i].to; dfs(j,deep+1); q[++tot]=x;td2[x]=tot; } } int ask(int L,int r) { int k=log(r-L+1)/log(2); if(g[L][k]<g[r-(1<<k)+1][k])return f[L][k]; else return f[r-(1<<k)+1][k]; } int main() { int i,j,k,x,y,root; scanf("%d%d",&n,&m); for(i=2;i<=n;++i)scanf("%d%d",&x,&y),add(x,y),prt[y]=x; for(i=1;i<=n;++i)if(!prt[i]){root=i;break;} dfs(root,1); for(i=1;i<=tot;i++)f[i][0]=q[i],g[i][0]=d[q[i]]; for(j=1;(1<<j)<=tot;j++) for(i=1;i<=tot;i++) { if(g[i][j-1]<g[i+(1<<(j-1))][j-1]) f[i][j]=f[i][j-1],g[i][j]=g[i][j-1]; else f[i][j]=f[i+(1<<(j-1))][j-1],g[i][j]=g[i+(1<<(j-1))][j-1]; } for(i=1;i<=m;i++) { scanf("%d%d",&x,&y); if(td1[x]>td2[y])swap(x,y); printf("%d\n",ask(td1[x],td2[y])); } return 0; }
标签:log eof 计算 bsp code std printf efi bre
原文地址:https://www.cnblogs.com/dsb-y/p/11944352.html