标签:htm gif dex ++ str stream 深度 query sizeof
推荐几个博客:https://www.cnblogs.com/JVxie/p/4854719.html Tarjan离线算法的基本思路及其算法实现
https://blog.csdn.net/shahdza/article/details/7779356 LCA题集
模板(题):
1.(POJ1470)http://poj.org/problem?id=1470
Tarjan离线算法
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 using namespace std; 6 const int maxn=1010; 7 const int maxm=500010; 8 struct Edge{ 9 int to,nxt; 10 }edge[maxn*2]; 11 struct Query{ 12 int q,nxt; 13 int index; 14 }query[maxm*2]; 15 int f[maxn],anc[maxn]; 16 bool vis[maxn]; 17 int head[maxn],tot; 18 int ans[maxm],h[maxm],tt,Q; 19 bool flag[maxn]; 20 int num[maxn]; 21 22 int find(int x) 23 { 24 if ( f[x]==-1 ) return x; 25 return f[x]=find(f[x]); 26 } 27 28 void merge(int x,int y) 29 { 30 int fx=find(x); 31 int fy=find(y); 32 if ( fx!=fy ) f[fx]=fy; 33 } 34 35 void addedge(int u,int v) 36 { 37 edge[tot].to=v; 38 edge[tot].nxt=head[u]; 39 head[u]=tot++; 40 } 41 42 void addquery(int u,int v,int index) 43 { 44 query[tt].q=v; 45 query[tt].nxt=h[u]; 46 query[tt].index=index; 47 h[u]=tt++; 48 query[tt].q=u; 49 query[tt].nxt=h[v]; 50 query[tt].index=index; 51 h[v]=tt++; 52 } 53 54 void init() 55 { 56 tot=0; 57 memset(head,-1,sizeof(head)); 58 tt=0; 59 memset(h,-1,sizeof(h)); 60 memset(vis,false,sizeof(vis)); 61 memset(f,-1,sizeof(f)); 62 memset(anc,0,sizeof(anc)); 63 } 64 65 void LCA(int u) 66 { 67 anc[u]=u; 68 vis[u]=true; 69 for ( int i=head[u];i!=-1;i=edge[i].nxt ) 70 { 71 int v=edge[i].to; 72 if ( vis[v] ) continue; 73 LCA(v); 74 merge(u,v); 75 anc[find(u)]=u; 76 } 77 for ( int i=h[u];i!=-1;i=query[i].nxt ) 78 { 79 int v=query[i].q; 80 if ( vis[v] ) ans[query[i].index]=anc[find(v)]; 81 } 82 } 83 84 int main() 85 { 86 int n,u,v,k; 87 while ( scanf("%d",&n)!=EOF ) 88 { 89 init(); 90 memset(flag,false,sizeof(flag)); 91 for ( int i=1;i<=n;i++ ) 92 { 93 scanf("%d:(%d)",&u,&k); 94 while ( k-- ) 95 { 96 scanf("%d",&v); 97 flag[v]=true; 98 addedge(u,v); 99 addedge(v,u); 100 } 101 } 102 scanf("%d",&Q); 103 for ( int i=0;i<Q;i++ ) 104 { 105 char ch; 106 cin>>ch; 107 scanf("%d %d)",&u,&v); 108 addquery(u,v,i); 109 } 110 int root; 111 for ( int i=1;i<=n;i++ ) 112 { 113 if ( !flag[i] ) 114 { 115 root=i; 116 break; 117 } 118 } 119 LCA(root); 120 memset(num,0,sizeof(num)); 121 for ( int i=0;i<Q;i++ ) num[ans[i]]++; 122 for ( int i=1;i<=n;i++ ) 123 { 124 if ( num[i]>0 ) printf("%d:%d\n",i,num[i]); 125 } 126 } 127 return 0; 128 }
2.(POJ1330)http://poj.org/problem?id=1330
倍增法在线算法
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 using namespace std; 6 const int maxn=1e4+10; 7 const int DEG=20; 8 struct Edge{ 9 int to,nxt; 10 }edge[maxn*2]; 11 int head[maxn],tot; 12 int fa[maxn][DEG]; //fa[i][j]表示节点i的第2^j个祖先 13 int deg[maxn]; 14 bool flag[maxn]; 15 16 void addedge(int u,int v) 17 { 18 edge[tot].to=v; 19 edge[tot].nxt=head[u]; 20 head[u]=tot++; 21 } 22 23 void init() 24 { 25 tot=0; 26 memset(head,-1,sizeof(head)); 27 } 28 29 void BFS(int root) 30 { 31 queue<int>que; 32 deg[root]=0; 33 fa[root][0]=root; 34 que.push(root); 35 while ( !que.empty() ) 36 { 37 int tmp=que.front(); 38 que.pop(); 39 for ( int i=1;i<DEG;i++ ) fa[tmp][i]=fa[fa[tmp][i-1]][i-1]; 40 for ( int i=head[tmp];i!=-1;i=edge[i].nxt ) 41 { 42 int v=edge[i].to; 43 if ( v==fa[tmp][0] ) continue; 44 deg[v]=deg[tmp]+1; 45 fa[v][0]=tmp; 46 que.push(v); 47 } 48 } 49 } 50 51 int LCA(int u,int v) 52 { 53 if ( deg[u]>deg[v] ) swap(u,v); 54 int hu=deg[u],hv=deg[v]; 55 int tu=u,tv=v; 56 for ( int det=hv-hu,i=0;det;det>>=1,i++ ) 57 { 58 if ( det&1 ) tv=fa[tv][i]; 59 } 60 if ( tu==tv ) return tu; 61 for ( int i=DEG-1;i>=0;i-- ) 62 { 63 if ( fa[tu][i]==fa[tv][i] ) continue; 64 tu=fa[tu][i]; 65 tv=fa[tv][i]; 66 } 67 return fa[tu][0]; 68 } 69 70 int main() 71 { 72 int T,n,u,v; 73 scanf("%d",&T); 74 while ( T-- ) 75 { 76 scanf("%d",&n); 77 init(); 78 memset(flag,false,sizeof(flag)); 79 for ( int i=1;i<n;i++ ) 80 { 81 scanf("%d%d",&u,&v); 82 addedge(u,v); 83 addedge(v,u); 84 flag[v]=true; 85 } 86 int root; 87 for ( int i=1;i<=n;i++ ) 88 { 89 if ( !flag[i] ) 90 { 91 root=i; 92 break; 93 } 94 } 95 BFS(root); 96 scanf("%d%d",&u,&v); 97 printf("%d\n",LCA(u,v)); 98 } 99 return 0; 100 }
练习题:
1.(HDOJ2586)http://acm.hdu.edu.cn/showproblem.php?pid=2586
题意:求给定两点之间的距离
分析:如果t是u,v的最近公共祖先,那么d[u,v]=d[u,root]+d[v,root]-2*d[t,root],所以我们只需要在倍增算法的BFS中每次更新深度时同时把距离一起更新掉即可
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 using namespace std; 6 const int maxn=4e4+10; 7 const int DEG=20; 8 const int inf=1e9; 9 struct Edge{ 10 int to,nxt,w; 11 }edge[maxn*2]; 12 int head[maxn],tot; 13 int fa[maxn][DEG]; //fa[i][j]表示节点i的第2^j个祖先 14 int deg[maxn]; 15 bool flag[maxn]; 16 int n,d[maxn]; 17 18 void addedge(int u,int v,int w) 19 { 20 edge[tot].to=v; 21 edge[tot].nxt=head[u]; 22 edge[tot].w=w; 23 head[u]=tot++; 24 } 25 26 void init() 27 { 28 tot=0; 29 memset(head,-1,sizeof(head)); 30 } 31 32 void BFS(int root) 33 { 34 queue<int>que; 35 for ( int i=1;i<=n;i++ ) d[i]=inf; 36 d[root]=0; 37 deg[root]=0; 38 fa[root][0]=root; 39 que.push(root); 40 while ( !que.empty() ) 41 { 42 int tmp=que.front(); 43 que.pop(); 44 for ( int i=1;i<DEG;i++ ) fa[tmp][i]=fa[fa[tmp][i-1]][i-1]; 45 for ( int i=head[tmp];i!=-1;i=edge[i].nxt ) 46 { 47 int v=edge[i].to; 48 int w=edge[i].w; 49 if ( v==fa[tmp][0] ) continue; 50 deg[v]=deg[tmp]+1; 51 d[v]=min(d[v],d[tmp]+w); 52 fa[v][0]=tmp; 53 que.push(v); 54 } 55 } 56 } 57 58 int LCA(int u,int v) 59 { 60 if ( deg[u]>deg[v] ) swap(u,v); 61 int hu=deg[u],hv=deg[v]; 62 int tu=u,tv=v; 63 for ( int det=hv-hu,i=0;det;det>>=1,i++ ) 64 { 65 if ( det&1 ) tv=fa[tv][i]; 66 } 67 if ( tu==tv ) return tu; 68 for ( int i=DEG-1;i>=0;i-- ) 69 { 70 if ( fa[tu][i]==fa[tv][i] ) continue; 71 tu=fa[tu][i]; 72 tv=fa[tv][i]; 73 } 74 return fa[tu][0]; 75 } 76 77 int main() 78 { 79 int T,u,v,w,m,x,ans; 80 scanf("%d",&T); 81 while ( T-- ) 82 { 83 scanf("%d%d",&n,&m); 84 init(); 85 memset(flag,false,sizeof(flag)); 86 for ( int i=1;i<n;i++ ) 87 { 88 scanf("%d%d%d",&u,&v,&w); 89 addedge(u,v,w); 90 addedge(v,u,w); 91 flag[v]=true; 92 } 93 int root; 94 for ( int i=1;i<=n;i++ ) 95 { 96 if ( !flag[i] ) 97 { 98 root=i; 99 break; 100 } 101 } 102 BFS(root); 103 for ( int i=1;i<=m;i++ ) 104 { 105 scanf("%d%d",&u,&v); 106 x=LCA(u,v); 107 ans=d[u]+d[v]-2*d[x]; 108 printf("%d\n",ans); 109 } 110 } 111 return 0; 112 }
2.(HDOJ2874)http://acm.hdu.edu.cn/showproblem.php?pid=2874
题意:给出一个森林,求给定两点之间的距离
分析:Tarjan离线算法,有多个根节点,每次询问时判断两个点是否处于同一个树上。LCA传入参数时需要传入当前的点,距离根节点的距离,根节点的编号。但是此题卡内存
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 using namespace std; 6 const int maxn=1e4+10; 7 const int maxm=1e6+10; 8 struct Edge{ 9 int to,nxt,w; 10 }edge[maxn*2]; 11 struct Query{ 12 int q,nxt; 13 int index; 14 }query[maxm*2]; 15 int f[maxn],anc[maxn]; 16 int head[maxn],tot; 17 int ans[maxm],h[maxm],tt,Q,belong[maxn]; 18 int n,d[maxn]; 19 20 int find(int x) 21 { 22 if ( f[x]==-1 ) return x; 23 return f[x]=find(f[x]); 24 } 25 26 void merge(int x,int y) 27 { 28 int fx=find(x); 29 int fy=find(y); 30 if ( fx!=fy ) f[fx]=fy; 31 } 32 33 void addedge(int u,int v,int w) 34 { 35 edge[tot].to=v; 36 edge[tot].nxt=head[u]; 37 edge[tot].w=w; 38 head[u]=tot++; 39 } 40 41 void addquery(int u,int v,int index) 42 { 43 query[tt].q=v; 44 query[tt].nxt=h[u]; 45 query[tt].index=index; 46 h[u]=tt++; 47 query[tt].q=u; 48 query[tt].nxt=h[v]; 49 query[tt].index=index; 50 h[v]=tt++; 51 } 52 53 void init() 54 { 55 tot=0; 56 memset(head,-1,sizeof(head)); 57 tt=0; 58 memset(h,-1,sizeof(h)); 59 memset(f,-1,sizeof(f)); 60 memset(anc,0,sizeof(anc)); 61 } 62 63 void LCA(int u,int deep,int root) 64 { 65 anc[u]=u; 66 belong[u]=root; 67 d[u]=deep; 68 for ( int i=head[u];i!=-1;i=edge[i].nxt ) 69 { 70 int v=edge[i].to; 71 int w=edge[i].w; 72 if ( belong[v]!=-1 ) continue; 73 LCA(v,deep+w,root); 74 merge(u,v); 75 anc[find(u)]=u; 76 } 77 for ( int i=h[u];i!=-1;i=query[i].nxt ) 78 { 79 int v=query[i].q; 80 if ( belong[v]==root ) 81 { 82 int sum=d[u]+d[v]-2*d[anc[find(v)]]; 83 ans[query[i].index]=sum; 84 } 85 } 86 } 87 88 int main() 89 { 90 int u,v,w,k,m,q,x; 91 while ( scanf("%d%d%d",&n,&m,&Q)!=EOF ) 92 { 93 init(); 94 for ( int i=1;i<=m;i++ ) 95 { 96 scanf("%d%d%d",&u,&v,&w); 97 addedge(u,v,w); 98 addedge(v,u,w); 99 } 100 for ( int i=0;i<Q;i++ ) 101 { 102 ans[i]=-1; 103 scanf("%d%d",&u,&v); 104 addquery(u,v,i); 105 } 106 memset(belong,-1,sizeof(belong)); 107 memset(d,-1,sizeof(d)); 108 for ( int i=1;i<=n;i++ ) 109 { 110 if ( belong[i]==-1 ) LCA(i,0,i); 111 } 112 for ( int i=0;i<Q;i++ ) 113 { 114 if ( ans[i]!=-1 ) printf("%d\n",ans[i]); 115 else printf("Not connected\n"); 116 } 117 } 118 return 0; 119 }
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 #include<vector> 6 using namespace std; 7 typedef long long LL; 8 9 const int maxm=2e4+10; 10 const int maxn=1e4+10; 11 const int maxq=2e6+10; 12 struct Node{ 13 int to; 14 int w; 15 int next; 16 }e[maxm]; 17 int eh[maxn],dis[maxn],pre[maxn],etol,vis[maxn]; 18 struct Query{ 19 int to; 20 int index; 21 int next; 22 }qe[maxq]; 23 int qh[maxn],ans[maxq/2],qtol; 24 int n,m,c; 25 26 void init() 27 { 28 etol=qtol=0; 29 memset(eh,-1,sizeof(eh)); 30 memset(qh,-1,sizeof(qh)); 31 } 32 33 void add1(int u,int v,int w) 34 { 35 e[etol].to=v; 36 e[etol].w=w; 37 e[etol].next=eh[u]; 38 eh[u]=etol++; 39 } 40 41 void add2(int u,int v,int id) 42 { 43 qe[qtol].index=id; 44 qe[qtol].to=v; 45 qe[qtol].next=qh[u]; 46 qh[u]=qtol++; 47 } 48 49 int Find(int u) 50 { 51 if(pre[u]!=u) pre[u]=Find(pre[u]); 52 return pre[u]; 53 } 54 55 void LCA(int u,int deep,int root) 56 { 57 pre[u]=u; 58 dis[u]=deep; 59 vis[u]=root; 60 for(int i=eh[u];~i;i=e[i].next) 61 { 62 int v=e[i].to; 63 if(vis[v]==-1) 64 { 65 LCA(v,deep+e[i].w,root); 66 pre[v]=u; 67 } 68 } 69 for(int i=qh[u];~i;i=qe[i].next) 70 { 71 int v=qe[i].to; 72 if(vis[v]==root) 73 ans[qe[i].index]=dis[v]+dis[u]-2*dis[Find(v)]; 74 } 75 } 76 77 78 int main() 79 { 80 while(~scanf("%d%d%d",&n,&m,&c)) 81 { 82 int u,v,w; 83 init(); 84 while(m--) 85 { 86 scanf("%d%d%d",&u,&v,&w); 87 add1(u,v,w); 88 add1(v,u,w); 89 } 90 for(int i=0;i<c;i++) 91 { 92 scanf("%d%d",&u,&v); 93 ans[i]=-1; 94 add2(u,v,i); 95 add2(v,u,i); 96 } 97 memset(vis,-1,sizeof(vis)); 98 for(int i=1;i<=n;i++){ 99 if(vis[i]==-1) 100 LCA(i,0,i); 101 } 102 for(int i=0;i<c;i++) 103 { 104 if(ans[i]==-1) puts("Not connected"); 105 else printf("%d\n",ans[i]); 106 } 107 } 108 return 0; 109 }
标签:htm gif dex ++ str stream 深度 query sizeof
原文地址:https://www.cnblogs.com/HDUjackyan/p/9102171.html