lca 例題 WK
阿新 • • 發佈:2017-05-20
clu span fat noip wap esp += log spa
codevs2370 小機房的樹
1 #include<iostream> 2 #include<cstdio> 3 #define maxn 110000 4 using namespace std; 5 int head[maxn],deep[maxn],sum[maxn][22],f[maxn][22]; 6 int n,m,num,ans; 7 struct node{ 8 int to,v,pre; 9 }e[maxn]; 10 void Insert(int from,int to,int v){ 11 e[++num].to=to;View Code12 e[num].v=v; 13 e[num].pre=head[from]; 14 head[from]=num; 15 } 16 void find_deep(int from,int now,int dep,int val){ 17 deep[now]=dep;f[now][0]=from;sum[now][0]=val; 18 for(int i=head[now];i;i=e[i].pre){ 19 int v=e[i].to; 20 if(v!=from)find_deep(now,v,dep+1,e[i].v);21 } 22 } 23 void find_father(){ 24 for(int i=1;i<=21;i++) 25 for(int j=1;j<=n;j++) 26 f[j][i]=f[f[j][i-1]][i-1]; 27 for(int i=1;i<=21;i++) 28 for(int j=1;j<=n;j++) 29 sum[j][i]=sum[f[j][i-1]][i-1]+sum[j][i-1]; 30 } 31 int get(int a,int delta){32 for(int i=0;i<=21;i++){ 33 if(delta&(1<<i))ans+=sum[a][i],a=f[a][i]; 34 } 35 return a; 36 } 37 int lca(int a,int b){ 38 if(deep[a]<deep[b])swap(a,b); 39 if(a==b)return 0; 40 a=get(a,deep[a]-deep[b]); 41 for(int i=21;i>=0;i--){ 42 if(f[a][i]!=f[b][i]){ 43 ans+=sum[a][i]+sum[b][i]; 44 a=f[a][i];b=f[b][i]; 45 } 46 } 47 if(a!=b)ans+=sum[a][0]+sum[b][0]; 48 } 49 int main(){ 50 scanf("%d",&n); 51 int x,y,z; 52 for(int i=1;i<n;i++){ 53 scanf("%d%d%d",&x,&y,&z); 54 Insert(x+1,y+1,z); 55 Insert(y+1,x+1,z); 56 } 57 find_deep(1,1,0,0); 58 find_father(); 59 scanf("%d",&m); 60 for(int i=1;i<=m;i++){ 61 scanf("%d%d",&x,&y); 62 ans=0;lca(x+1,y+1); 63 printf("%d\n",ans); 64 } 65 }
cogs1439. [NOIP2013]貨車運輸
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 #define maxn 10010 8 #define maxm 50010 9 int n,m,f[maxn][20],sum[maxn][20],fa[maxn],num,p,dep[maxn],head[maxn]; 10 bool vis[maxn]; 11 struct node{ 12 int f,to,v; 13 }a[maxm]; 14 struct Edge{ 15 int pre,v,to; 16 }e[maxm]; 17 int cmp(node x,node y){return x.v>y.v;} 18 int find(int x){ 19 if(fa[x]==x)return fa[x]; 20 else return fa[x]=find(fa[x]); 21 } 22 int connect(int x,int y){ 23 int f1=find(x),f2=find(y); 24 if(f1==f2)return 0; 25 else fa[f1]=f2;return 1; 26 } 27 void Insert(int from,int to,int v){ 28 e[++num].v=v; 29 e[num].to=to; 30 e[num].pre=head[from]; 31 head[from]=num; 32 } 33 void dfs(int now,int father,int deep){ 34 vis[now]=1; 35 dep[now]=deep; 36 for(int i=head[now];i;i=e[i].pre){ 37 int v=e[i].to; 38 if(v==father)continue; 39 f[v][0]=now; 40 sum[v][0]=e[i].v; 41 dfs(v,now,deep+1); 42 } 43 } 44 int lca(int x,int y){ 45 if(x==y)return 0; 46 int ans=0x3f3f3f3f; 47 if(dep[x]<dep[y])swap(x,y); 48 for(int i=18;i>=0;i--){ 49 if(dep[f[x][i]]>=dep[y]&&f[x][i]!=0)ans=min(ans,sum[x][i]),x=f[x][i]; 50 } 51 if(x==y)return ans; 52 for(int i=18;i>=0;i--){ 53 if(f[x][i]!=f[y][i]){ 54 ans=min(ans,sum[x][i]); 55 ans=min(ans,sum[y][i]); 56 x=f[x][i];y=f[y][i]; 57 } 58 } 59 ans=min(sum[x][0],ans);ans=min(sum[y][0],ans); 60 return ans; 61 } 62 int main(){ 63 //freopen("Cola.txt","r",stdin); 64 freopen("truck.in","r",stdin); 65 freopen("truck.out","w",stdout); 66 memset(sum,127/3,sizeof(sum)); 67 int x,y,z; 68 scanf("%d%d",&n,&m); 69 for(int i=1;i<=m;i++)scanf("%d%d%d",&a[i].f,&a[i].to,&a[i].v); 70 for(int i=1;i<=n;i++)fa[i]=i; 71 sort(a+1,a+m+1,cmp);int cnt=0; 72 for(int i=1;i<=m;i++){ 73 if(connect(a[i].f,a[i].to)){ 74 Insert(a[i].f,a[i].to,a[i].v); 75 Insert(a[i].to,a[i].f,a[i].v); 76 cnt++;if(cnt==n-1)break; 77 } 78 } 79 for(int i=1;i<=n;i++)if(!vis[i])dfs(i,0,1); 80 for(int j=1;(1<<j)<=n;j++) 81 for(int i=1;i<=n;i++) 82 if(f[f[i][j-1]][j-1]!=0){ 83 f[i][j]=f[f[i][j-1]][j-1]; 84 sum[i][j]=min(sum[i][j-1],sum[f[i][j-1]][j-1]); 85 } 86 scanf("%d",&p); 87 for(int i=1;i<=p;i++){ 88 scanf("%d%d",&x,&y); 89 if(find(x)!=find(y)){printf("-1\n");continue;} 90 printf("%d\n",lca(x,y)); 91 } 92 }View Code
hdu2586
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <vector> 5 using namespace std; 6 vector<int> v[41000]; 7 vector<int> w[41000]; 8 int f[41000][21];//f[i][j]表示i點向上2^j層的祖先 9 int sum[41000][21];//g[i][j]表示i點到從i向上2^j層的祖先的距離 10 int dep[41000]; 11 int n,m; 12 void dfs(int pos,int pre,int depth) 13 { 14 dep[pos]=depth; 15 for(int i=0;i<v[pos].size();i++) 16 { 17 int t=v[pos][i]; 18 if(t==pre) continue; 19 f[t][0]=pos; 20 sum[t][0]=w[pos][i]; 21 dfs(t,pos,depth+1); 22 } 23 } 24 int query(int a,int b) 25 { 26 int Sum=0; 27 if(dep[a]<dep[b]) swap(a,b);//深度較深的點 28 for(int i=20;i>=0;i--)//找到a在深度dep[b]處的祖先 29 { 30 if(dep[f[a][i]]>=dep[b]) 31 { 32 Sum+=sum[a][i];//a到該祖先的距離 33 a=f[a][i]; 34 } 35 } 36 if(a==b) return Sum;//挪到相同深度後如果在同一點直接return 37 int x; 38 for(int i=20;i>=0;i--)//否則a和b一起往上跳 39 { 40 if(f[a][i]!=f[b][i]) 41 { 42 Sum+=sum[a][i]; 43 a=f[a][i]; 44 Sum+=sum[b][i]; 45 b=f[b][i]; 46 } 47 } 48 return Sum+sum[a][0]+sum[b][0];//最後跳到最近公共祖先的下一層,所以要再加上上一層 49 } 50 int main() 51 { 52 int T; 53 cin>>T; 54 while(T--) 55 { 56 scanf("%d%d",&n,&m); 57 memset(dep,-1,sizeof(dep)); 58 memset(f,0,sizeof(f)); 59 memset(sum,0,sizeof(sum)); 60 for(int i=0;i<n;i++)//md 61 v[i].clear(),w[i].clear(); 62 for(int i=1;i<n;i++) 63 { 64 int x,y,c; 65 cin>>x>>y>>c; 66 v[x].push_back(y); 67 w[x].push_back(c); 68 v[y].push_back(x); 69 w[y].push_back(c); 70 } 71 int xxx=v[1].size(); 72 dfs(1,0,1);//dfs處理出每個點的深度,以及各種... 73 74 for(int i=1;1<<i<=n;i++) 75 for(int j=1;j<=n;j++) 76 f[j][i]=f[f[j][i-1]][i-1], 77 sum[j][i]=sum[f[j][i-1]][i-1]+sum[j][i-1]; 78 for(int i=1;i<=m;i++) 79 { 80 int x,y; 81 cin>>x>>y; 82 if(x==y) cout<<"0"<<endl; 83 else cout<<query(x,y)<<endl; 84 } 85 } 86 return 0; 87 }View Code
洛谷3379
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 #define maxn 500010 5 int n,m,s,f[maxn][22],deep[maxn],head[maxn],num; 6 struct node{ 7 int to,pre; 8 }e[maxn<<1]; 9 int qread(){ 10 int x=0,j=1; 11 char ch=getchar(); 12 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)j=-1;ch=getchar();} 13 while(ch<=‘9‘&&ch>=‘0‘){x=x*10+ch-‘0‘;ch=getchar();} 14 return x*j; 15 } 16 void Insert(int from,int to){ 17 e[++num].to=to; 18 e[num].pre=head[from]; 19 head[from]=num; 20 } 21 void find_deep(int from,int now,int dep){ 22 f[now][0]=from;deep[now]=dep; 23 for(int i=head[now];i;i=e[i].pre){ 24 int v=e[i].to; 25 if(v!=from){ 26 find_deep(now,v,dep+1); 27 } 28 } 29 } 30 void find_father(){ 31 for(int j=1;j<=21;j++) 32 for(int i=1;i<=n;i++) 33 f[i][j]=f[f[i][j-1]][j-1]; 34 } 35 int get(int a,int delta){ 36 for(int i=0;i<=21;i++){ 37 if(delta&(1<<i))a=f[a][i]; 38 }return a; 39 } 40 int lca(int a,int b){ 41 if(deep[a]<deep[b])swap(a,b); 42 a=get(a,deep[a]-deep[b]); 43 if(a==b) return a; 44 for(int i=21;i>=0;i--){ 45 if(f[a][i]!=f[b][i]){ 46 a=f[a][i],b=f[b][i]; 47 } 48 } 49 return f[a][0]; 50 } 51 int main(){ 52 n=qread(),m=qread(),s=qread(); 53 int x,y; 54 for(int i=1;i<=n-1;i++){ 55 x=qread();y=qread(); 56 Insert(x,y); 57 Insert(y,x); 58 } 59 find_deep(s,s,0); 60 find_father(); 61 for(int i=1;i<=m;i++){ 62 x=qread();y=qread(); 63 int ans=lca(x,y); 64 printf("%d\n",ans); 65 } 66 return 0; 67 }View Code
lca 例題 WK