Social Net ZOJ - 3649
题意:
反正原题题意我是看不懂...
参考:http://www.cnblogs.com/names-yc/p/4922867.html
给出一幅图,求最大生成树,输出边权之和,并在这棵树上进行查询操作:给出两个结点编号x和y,求从x到y的路径上,由每个结点的权值构成的序列中的极差大小——要求,被减数要在减数的后面,即形成序列{a1,a2…aj …ak…an},求ak-aj (k>=j)的最大值。
做法:
首先kruskal求一下最大生成树。然后做倍增dp。
p[i]表示i号节点的权值
anc[i][j]表示i号节点的第2^j级祖先
根据倍增的基本思想,有:
maxn[i][j]表示从i号节点出发向上走,共走过2^j个节点(包含i号节点),这些节点中点权的最大值
$maxn[i][0]=p[i]$
$maxn[i][j]=max(maxn[i][j-1],maxn[anc[i][j-1]][j-1])$
minn[i][j]表示从i号节点出发向上走,共走过2^j个节点(包含i号节点),这些节点中点权的最小值
$minn[i][0]=p[i]$
$minn[i][j]=min(minn[i][j-1],minn[anc[i][j-1]][j-1])$
maxans[i][j]表示从i号节点出发向上走,共走过2^j个节点(包含i号节点),这些节点的权值按经过顺序构成的序列{a1,a2…aj …ak…an}中,求ak-aj(k>=j)的最大值。
$maxans[i][0]=0$
$maxans[i][j]=max(maxans[i][j-1],maxans[anc[i][j-1]][j-1],maxn[anc[i][j-1]][j-1]-minn[i][j-1])$
其含义为:最大差值要么是在前一半产生,要么在后一半产生,要么就是后一半的最大值减去前一半的最小值。
minans[i][j]表示从i号节点出发向上走,共走过2^j个节点(包含i号节点),这些节点的权值按经过顺序的构成的序列{a1,a2…aj …ak…an}中,求ak-aj(k<=j)的最大值。(这个数组的名字其实不太对...不要管它)
$minans[i][0]=0$
$minans[i][j]=max(minans[i][j-1],minans[anc[i][j-1]][j-1],maxn[i][j-1]-minn[anc[i][j-1]][j-1])$
其含义为:最大差值要么是在前一半产生,要么在后一半产生,要么就是前一半的最大值减去后一半的最小值。
以上都可以在dfs过程中完成。
求结果的过程,也可以视为倍增lca,但是在点“上移”的过程中,要求把移过的部分的答案更新到当前答案上。
设lca(x,y)=z。从x到y的路径,可以视为x到z,z再到y。那么,答案就是max(x到z路径中最大答案,z到y路径中最大答案,z权值-x到z路径中最小值,z到y路径中最大值-z权值,z到y路径中最大答案-x到z路径中最大答案)。
在x上移时,上移之后的最大答案就是max(x已经过部分产生的最大答案,将要上移部分的最大值-x已经过部分的最小值,将要上移部分的最大答案(在maxans中取))。
在y上移时,上移之后的最大答案就是max(y已经过部分产生的最大答案,y已经过部分的最大值-将要上移部分的最小值,将要上移部分的最大答案(在minans中取))。
错误记录(本地):
1.由于x和y有顺序,不能写成形如47行
2.缺少63,64行
3.缺少75-78行,由于按这个方法写,上移过程中,当前点不会被更新进已有答案
http://www.xuebuyuan.com/1162519.html1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 struct E1 7 { 8 int a,b,w; 9 friend bool operator<(const E1& a,const E1& b) 10 { 11 return a.w>b.w; 12 } 13 }e1[50100]; 14 struct Edge 15 { 16 int to,d,nxt; 17 }e[100100]; 18 int fa[50100],p[50100],n,m,ne,f1[50100],log2n,deep[50100],q,ans1; 19 int minn[50100][17],maxn[50100][17],minans[50100][17],maxans[50100][17],anc[50100][17]; 20 int find(int x) 21 { 22 return fa[x]==x?x:fa[x]=find(fa[x]); 23 } 24 void dfs(int x,int fa) 25 { 26 int i,k; 27 minn[x][0]=maxn[x][0]=p[x]; 28 //minans[x][0]=maxans[x][0]=0; 29 for(i=1;i<=log2n;i++) 30 { 31 anc[x][i]=anc[anc[x][i-1]][i-1]; 32 minn[x][i]=min(minn[x][i-1],minn[anc[x][i-1]][i-1]); 33 maxn[x][i]=max(maxn[x][i-1],maxn[anc[x][i-1]][i-1]); 34 minans[x][i]=max(max(minans[anc[x][i-1]][i-1],minans[x][i-1]),maxn[x][i-1]-minn[anc[x][i-1]][i-1]); 35 maxans[x][i]=max(max(maxans[anc[x][i-1]][i-1],maxans[x][i-1]),maxn[anc[x][i-1]][i-1]-minn[x][i-1]); 36 } 37 for(k=f1[x];k!=0;k=e[k].nxt) 38 if(e[k].to!=fa) 39 { 40 deep[e[k].to]=deep[x]+1; 41 anc[e[k].to][0]=x; 42 dfs(e[k].to,x); 43 } 44 } 45 int get(int x,int y) 46 { 47 //if(deep[x]<deep[y]) swap(x,y); 48 int t,i,ansx=0,ansy=0,minx=p[x],maxy=p[y]; 49 for(t=deep[x]-deep[y],i=0;t>0;t>>=1,i++) 50 if(t&1) 51 { 52 ansx=max(ansx,max(maxans[x][i],maxn[x][i]-minx)); 53 minx=min(minx,minn[x][i]); 54 x=anc[x][i]; 55 } 56 for(t=deep[y]-deep[x],i=0;t>0;t>>=1,i++) 57 if(t&1) 58 { 59 ansy=max(ansy,max(minans[y][i],maxy-minn[y][i])); 60 maxy=max(maxy,maxn[y][i]); 61 y=anc[y][i]; 62 } 63 if(x==y) 64 return max(max(ansx,ansy),maxy-minx); 65 for(i=log2n;i>=0;i--) 66 if(anc[x][i]!=anc[y][i]) 67 { 68 ansx=max(ansx,max(maxans[x][i],maxn[x][i]-minx)); 69 minx=min(minx,minn[x][i]); 70 ansy=max(ansy,max(minans[y][i],maxy-minn[y][i])); 71 maxy=max(maxy,maxn[y][i]); 72 x=anc[x][i]; 73 y=anc[y][i]; 74 } 75 ansx=max(ansx,max(maxans[x][0],maxn[x][0]-minx)); 76 minx=min(minx,minn[x][0]); 77 ansy=max(ansy,max(minans[y][0],maxy-minn[y][0])); 78 maxy=max(maxy,maxn[y][0]); 79 return max(max(max(ansx,ansy),maxy-minx),max(p[anc[x][0]]-minx,maxy-p[anc[y][0]])); 80 } 81 int main() 82 { 83 int i,t1,t2,a,b; 84 while(scanf("%d",&n)==1) 85 { 86 log2n=log2(n); 87 ne=0;ans1=0; 88 memset(f1,0,sizeof(f1)); 89 memset(minn,0x3f,sizeof(minn)); 90 memset(maxn,0,sizeof(maxn)); 91 memset(minans,0,sizeof(minans)); 92 memset(maxans,0,sizeof(maxans)); 93 for(i=1;i<=n;i++) 94 scanf("%d",&p[i]); 95 scanf("%d",&m); 96 for(i=1;i<=m;i++) 97 scanf("%d%d%d",&e1[i].a,&e1[i].b,&e1[i].w); 98 sort(e1+1,e1+m+1); 99 for(i=1;i<=n;i++) 100 fa[i]=i; 101 for(i=1;i<=m;i++) 102 { 103 t1=find(e1[i].a); 104 t2=find(e1[i].b); 105 if(t1==t2) continue; 106 e[++ne].to=e1[i].b; 107 e[ne].nxt=f1[e1[i].a]; 108 e[ne].d=e1[i].w; 109 f1[e1[i].a]=ne; 110 e[++ne].to=e1[i].a; 111 e[ne].nxt=f1[e1[i].b]; 112 e[ne].d=e1[i].w; 113 f1[e1[i].b]=ne; 114 fa[t1]=t2; 115 ans1+=e1[i].w; 116 } 117 printf("%d\n",ans1); 118 dfs(1,0); 119 scanf("%d",&q); 120 while(q--) 121 { 122 scanf("%d%d",&a,&b); 123 printf("%d\n",get(a,b)); 124 } 125 } 126 return 0; 127 }