tarjan求lca——luogu3319lca模板与1967货车运输
2018-01-04 17:38
375 查看
lca的tarjan求法,与并查集结合,离线完成
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
const int maxn=500009;
using namespace std;
struct node{
int v,id,next;
node(int a=0,int b=0,int c=0):v(a),id(b),next(c){}
}edge[2*maxn],ques[2*maxn];
int n,m,s,anslca[maxn],fa[maxn],cnt=0;
int head[maxn],qhead[maxn];
bool vis[maxn];
int add(node e[],int hd[],int u,int v,int w){
e[++cnt]={v,w,hd[u]};
hd[u]=cnt;
e[++cnt]={u,w,hd[v]};
hd[v]=cnt;
}
int find(int x) {
if(fa[x]==x)return x;
else return fa[x]=find(fa[x]) ;
}
void tarlca(int u) {
fa[u]=u; vis[u]=1;
for(int i=head[u]; i>0; i=edge[i].next) {
int v=edge[i].v;
if(!fa[v]){tarlca(v);fa[v]=u;}
}
for(int i=qhead[u];i>0;i=ques[i].next){
int v=ques[i].v,id=ques[i].id;
if(vis[v]){
anslca[id]=find(v);
}
}
}
int main(){
memset(head,0,sizeof(head));
memset(qhead,0,sizeof(qhead));
int a,b;
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<n;i++){
scanf("%d%d",&a,&b);
add(edge,head,a,b,0);
}
cnt=0;
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
add(ques,qhead,a,b,i);
}
tarlca(s);
for(int i=0;i<m;i++)cout<<anslca[i]<<endl;
}
又写一遍货车运输
并查集和搜索的结合
有一个坑点,路径上的值可能为0,那么最小值就是0啦,可是要和不能到达一样,要输出-1.不知道是代码的问题还是程序的问题。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
const int maxn=500009;
using namespace std;
struct node{
int v,id,next;
node(int a=0,int b=0,int c=0):v(a),id(b),next(c){}
}edge[2*maxn],ques[2*maxn];
int n,m,s,anslca[maxn],fa[maxn],cnt=0;
int head[maxn],qhead[maxn];
bool vis[maxn];
int add(node e[],int hd[],int u,int v,int w){
e[++cnt]={v,w,hd[u]};
hd[u]=cnt;
e[++cnt]={u,w,hd[v]};
hd[v]=cnt;
}
int find(int x) {
if(fa[x]==x)return x;
else return fa[x]=find(fa[x]) ;
}
void tarlca(int u) {
fa[u]=u; vis[u]=1;
for(int i=head[u]; i>0; i=edge[i].next) {
int v=edge[i].v;
if(!fa[v]){tarlca(v);fa[v]=u;}
}
for(int i=qhead[u];i>0;i=ques[i].next){
int v=ques[i].v,id=ques[i].id;
if(vis[v]){
anslca[id]=find(v);
}
}
}
int main(){
memset(head,0,sizeof(head));
memset(qhead,0,sizeof(qhead));
int a,b;
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<n;i++){
scanf("%d%d",&a,&b);
add(edge,head,a,b,0);
}
cnt=0;
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
add(ques,qhead,a,b,i);
}
tarlca(s);
for(int i=0;i<m;i++)cout<<anslca[i]<<endl;
}
又写一遍货车运输
并查集和搜索的结合
有一个坑点,路径上的值可能为0,那么最小值就是0啦,可是要和不能到达一样,要输出-1.不知道是代码的问题还是程序的问题。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; const int MaxN=10005,MaxM=100005,inf=0x3f3f3f3f; struct LinkType { int a,b,c; }; LinkType w[MaxM],e[MaxM],q[MaxM]; int he[MaxN],hq[MaxN]; int father[MaxN],fak[MaxN],mv[MaxN],mark[MaxN],ans[MaxM]; int ance[MaxN]; int N,M,Q,e0=0,q0=0; void Addq(int x,int y,int z) //hr[]存查询的起点,q[].a查询的终点,q[].c对应的输入序号 .b前向星链接 { q0++; q[q0].a=y; q[q0].b=hq[x]; hq[x]=q0; q[q0].c=z; } void Adde(int x,int y,int z) //最小生成树加边 { e0++; e[e0].a=y; e[e0].b=he[x]; he[x]=e0; e[e0].c=z; } void Read() { int i; scanf("%d%d",&N,&M); for(i=1; i<=M; i++) scanf("%d%d%d",&w[i].a,&w[i].b,&w[i].c); } bool cmp(LinkType a,LinkType b) { return a.c>b.c; } int Find(int x) { int fa; if(father[x]==x) return x; fa=Find(father[x]); mv[x]=min(mv[x],mv[father[x]]);//找到当前子集合的路径上的最大值 return father[x]=fa; } void Rebuild() { //求最小生成树,并建立树,存储在数组e. int i,r1,r2; for(i=1; i<=N; i++)father[i]=i; sort(w+1,w+1+M,cmp); for(i=1; i<=M; i++) { r1=Find(w[i].a); r2=Find(w[i].b); if(r1!=r2) { father[r2]=r1; Adde(r1,r2,w[i].c); Adde(r2,r1,w[i].c); } } for(int i=1;i<=N;i++)Find(i); memcpy(fak,father,sizeof(father)) ;//原来的并查集还用的着。 } void Tarjan(int x,int fa) { int i,y,r1,r2; father[x]=x; mv[x]=inf;//最大过路费 // ance[x]=x; for(i=he[x]; i; i=e[i].b) { //前向星找到当前节点的孩子,递归 y=e[i].a; if(y==fa)continue; Tarjan(y,x); father[y]=x;//合并集合 mv[y]=e[i].c; // ance[Find(x)]=x; } mark[x]=1; for(i=hq[x]; i; i=q[i].b) { //处理与x相关的查询,的序号 y=q[i].a;//找到与x相连的y, 找到y所在的集合序号,添加上其查输入的次序 Find(y);//找到当前节点到子树祖先路径上的最小值。 if(mark[y]) { // cout<<" ance x-y:"<<x<<"-"<<y <<"="<<ance[Find(y)]<<" max"<<min(mv[x],mv[y])<<" 输入序号"<<q[i].c<<endl; ans[q[i].c]=min(mv[x],mv[y]); } } } void Solve() { Rebuild(); scanf("%d",&Q);int a,b; for(int i=1; i<=Q; i++) { //tarjan,查询队列 scanf("%d%d",&a,&b); if(fak[a]==fak[b]) { Addq(a,b,i);//加边,起点,存hq[],终点q[].a,序号 q[].c Addq(b,a,i); } } for(int i=1;i<=N;i++)if(!mark[i])Tarjan(i,0); for(int i=1; i<=Q; i++){ if(ans[i]==inf||ans[i]==0)ans[i]=-1; printf("%d\n",ans[i]); } } int main() { Read(); Solve(); return 0; }
相关文章推荐
- NOIP 2013 货车运输(最大生成树+倍增LCA/Tarjan)
- Luogu1967 [NOIP2013] 货车运输 解题报告【Kruskal】【LCA】【倍增】
- 【洛谷】1967 [noip2013]货车运输 最小生成树+LCA
- 洛谷P1967货车运输(最大生成树 && LCA倍增)
- [最大生成树+LCA]NOIP 2013——货车运输
- [洛谷 P1967] 货车运输 (最大生成树 lca)
- 【模板】tarjanLCA [2017年6月计划 学习tarjanLCA]
- HDU2586 LCA_Tarjan模板题
- 洛谷1967 火车运输 kruskal求最大生成树 倍增LCA维护最小值
- 【cogs1439】货车运输 生成树+lca
- poj3694(lca + tarjan求桥模板)
- 洛谷1967 货车运输 NOIP2013
- Tarjan_LCA模板
- [NOIP2013] 货车运输 最大生成树 LCA
- NOIP2013 货车运输 LCA倍增+最大生成树
- noip2013货车运输(lca)
- 【P1843】货车运输(最大生成树+LCA)
- POJ1470 (LCA_Tarjan模板题)
- 洛谷1967 火车运输 kruskal求最大生成树 倍增LCA维护最小值
- NOIP2013 货车运输(最大生成树+LCA)