How far away ? HDU - 2586
生活随笔
收集整理的這篇文章主要介紹了
How far away ? HDU - 2586
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
點擊打開鏈接1??點擊打開鏈接2
?理解這個算法一定要抓住`遞推`的思想(也有遞歸在里面,?也要抓住).
????Tarjan是利用并查集實現的,?在遞推過程中,?一棵樹的root節點代表這棵樹(聯系并查集來想),?這樣做的好處是,?如果問點i與j的lca,?我們只要找i,j都屬于的最小的哪棵子樹就行了,?因為該子樹就是我們的答案.?那如何確定是那顆子樹呢??這一點后面再解釋一下.
????下面說Tarjan最巧妙的點了.?因為是在建樹的過程中計算所有query,?也就表示我們此刻是否能計算某一query對(u,v)的條件是?:?u和v是否都已經遍歷過.?所以我們可以在遍歷到點v(假設經歷v的時間比u晚)的時候把query給計算出來.?比如lcm(u,v)就是find(u).?那此刻的find(v)和lcm(u,v)相不相等呢??答案是不相等,?至少在我的代碼實現上不相等.?因為father[x]的更新是在`遞歸回去`的時候更新的,?而此刻在遍歷v點,?還沒遞歸回去呢,?father[v]當然也就沒更新啦.點擊打開鏈接 3
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; const int maxn=40010; struct node {int from,to,weight,lca,next; }edge[maxn*2],qedge[maxn]; int first[maxn],qfirst[maxn],index,index1; int m,n; int father[maxn],vis[maxn],dist[maxn],res[maxn][3]; void init() {memset(vis,0,sizeof(vis));memset(dist,0,sizeof(dist));memset(first,0,sizeof(first));memset(qfirst,0,sizeof(qfirst));index=index1=1; } void add(int u,int v,int w) {edge[index].to=v;edge[index].weight=w;edge[index].next=first[u];first[u]=index++; } void qadd(int u,int v,int w) {qedge[index1].to=v;qedge[index1].weight=w;qedge[index1].next=qfirst[u];qfirst[u]=index1++; } int Find(int x) {// if(father[x]==x)// return x;// return father[x]=Find(father[x]);int root=x;while(root!=father[root])root=father[root];int j;while(root!=father[x]){j=father[x];father[x]=root;x=j;}return root; } void tarjan(int u) {vis[u]=1;father[u]=u;for(int i=first[u];i;i=edge[i].next){int v=edge[i].to;if(!vis[v]){dist[v]=dist[u]+edge[i].weight;tarjan(v);//Union(u,v);father[v]=u;// cout<<v<<"father :"<<father[u]<<endl;}}for(int i=qfirst[u];i;i=qedge[i].next){int v=qedge[i].to;if(vis[v]){res[qedge[i].weight][2]=Find(v);//最近的公共祖先// cout<<res[i][0]<<" and "<<res[i][1]<<" lca :"<<res[i][2]<<endl;}} } int main() {int T;int u,v,w;scanf("%d",&T);while(T--){init();scanf("%d%d",&n,&m);for(int i=1;i<n;i++){scanf("%d%d%d",&u,&v,&w);add(u,v,w);add(v,u,w);}for(int i=0;i<m;i++){scanf("%d%d",&u,&v);qadd(u,v,i);qadd(v,u,i);res[i][0]=u;res[i][1]=v;}dist[1]=0;tarjan(1);for(int i=0;i<m;++i){//cout<<res[i][2]<<" ";printf("%d\n",dist[res[i][0]]+dist[res[i][1]]-2*dist[res[i][2]]);}}return 0; } /* 1 11 3 1 2 1 1 3 2 2 5 3 3 6 4 5 8 5 5 9 6 6 10 7 6 11 8 2 4 1 3 7 2 8 9 10 11 9 10 */wa的一個: #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; const int maxn=40010; struct node {int from,to,weight,lca,next; }edge[maxn*2],qedge[maxn]; int first[maxn],qfirst[maxn],index,index1; int m,n; int father[maxn],vis[maxn],dist[maxn]; void init() {memset(vis,0,sizeof(vis));memset(dist,0,sizeof(dist));memset(first,-1,sizeof(first));memset(qfirst,-1,sizeof(qfirst));index=index1=0; } void add(int u,int v,int w) {edge[index].to=v;edge[index].weight=w;edge[index].next=first[u];first[u]=index++; } void qadd(int u,int v) {qedge[index1].from=u;qedge[index1].to=v;qedge[index1].lca=-1;qedge[index1].next=qfirst[u];qfirst[u]=index1++; } int Find(int x) {if(father[x]==x)return x;return father[x]=Find(father[x]); } void Union(int x,int y) {x=Find(x);y=Find(y);if(x!=y)father[y]=x; } void tarjan(int u) {vis[u]=1;father[u]=u;//ance[u]=father[u]=u;for(int i=first[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(!vis[v]){dist[v]=dist[u]+edge[i].weight;tarjan(v);//Union(u,v);father[v]=u;}}for(int i=qfirst[u];i!=-1;i=qedge[i].next){int v=qedge[i].to;if(vis[v]){if(v%2){qedge[i+1].lca=qedge[i].lca=Find(v);}elseqedge[i].lca=qedge[i-1].lca=Find(v);//ance[Find(v)];}} } int main() {int T;scanf("%d",&T);while(T--){init();scanf("%d%d",&n,&m);for(int i=1;i<n;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);add(u,v,w);add(v,u,w);}for(int i=0;i<m;i++){int u,v;scanf("%d%d",&u,&v);qadd(u,v);qadd(v,u);}dist[1]=0;tarjan(1);for(int i=0;i<m;++i){int j=i*2;int u=qedge[j].from;int v=qedge[j].to;int lca=qedge[j].lca;printf("%d\n",dist[u]+dist[v]-2*dist[lca]);}}return 0; }《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的How far away ? HDU - 2586的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu 1588 Gauss Fibon
- 下一篇: 面向抽象编程