hdu4916 Count on the path
调了好久。。。。
•把树视为以1为根的有向树,然后将1删除
•原树变为一个森林,并且任一棵树的根节点均为原树中1的子节点
•只需要考虑最小编号前3小的三棵树
•记f[x][y]为去掉x和y两棵树后的最小值
•记dui[u]为u节点所在的树的根节点
•记dp[u]为在dui[u]这颗树中,不在路径<dui[u], u>上的节点编号最小值
•对于经过根节点的询问<u, v>
•ans<u, v> = min(dp[u], dp[v], f[bel[u]][bel[v]])
•维护g[x][0]和g[x][1],分别表示以x的子节点为根的子树中,编号最小值和次小值
•记F[x]为删除<bel[x], x>这条路径及x的子树,编号的最小值
•dp[u] = min(F[u], g[u][0])
•时间复杂度O(N),空间复杂度O(N)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<string> 5 #include<cstring> 6 #include<cmath> 7 #include<algorithm> 8 #define re(i,l,r) for(int i=(l);i<=(r);i++) 9 #define rre(i,r,l) for(int i=(r);i>=(l);i--) 10 using namespace std; 11 const int xxx=1000010; 12 int n,m,head[xxx],Next[xxx<<1],zhi[xxx<<1],fa[xxx],ed; 13 int g[xxx][2],f[4][4],dui[xxx],F[xxx],dp[xxx],xiao[3]; 14 void add(int a,int b) 15 { 16 Next[++ed]=head[a],head[a]=ed,zhi[ed]=b; 17 Next[++ed]=head[b],head[b]=ed,zhi[ed]=a; 18 } 19 const int L=1e7; 20 char in[L],*In,*End; 21 char getc(){ 22 if(In==End){ 23 End=in+fread(in,1,L,stdin); 24 if(in==End) return 0; 25 In=in; 26 } 27 return *In++; 28 } 29 int inin(int &x){ 30 static char c; 31 for(;c=getc(),!isdigit(c) && c;); 32 if(!c) return 0; 33 for(x=0;isdigit(c);c=getc()) (x*=10)+=c-'0'; 34 return 1; 35 } 36 void dfs(int x) 37 { 38 g[x][0]=2147483647;g[x][1]=2147483647; 39 for(int i=head[x];i;i=Next[i])if(zhi[i]!=fa[x]) 40 { 41 fa[zhi[i]]=x; 42 dfs(zhi[i]); 43 int temp=min(g[zhi[i]][0],zhi[i]); 44 if(temp<=g[x][0]) 45 g[x][1]=g[x][0], 46 g[x][0]=temp; 47 else g[x][1]=min(g[x][1],temp); 48 // else g[x][1]=min(g[x][1],g[zhi[i]][0]); 49 } 50 } 51 void dfsxxx(int x,int t) 52 { 53 dui[x]=t; 54 for(int i=head[x];i;i=Next[i])if(zhi[i]!=fa[x]) 55 dfsxxx(zhi[i],t); 56 } 57 void dfs2(int x) 58 { 59 if(x>1&&fa[x]!=1) 60 if(g[fa[x]][0]==min(g[x][0],x)) 61 F[x]=min(F[fa[x]],g[fa[x]][1]); 62 else F[x]=min(F[fa[x]],g[fa[x]][0]);else ; 63 if(fa[x]==1)F[x]=2147483647; 64 dp[x]=min(F[x],g[x][0]); 65 for(int i=head[x];i;i=Next[i])if(zhi[i]!=fa[x]) 66 dfs2(zhi[i]); 67 } 68 //void dfs3(int x) 69 //{ 70 // for(int i=head[x];i;i=Next[i])if(zhi[i]!=fa[x]) 71 // dfs3(zhi[i]); 72 //} 73 int hhh(int x) 74 { 75 x=dui[x]; 76 if(min(x,g[x][0])==xiao[0])return 0; 77 else if(min(x,g[x][0])==xiao[1])return 1; 78 else if(min(x,g[x][0])==xiao[2])return 2; 79 else return 3; 80 } 81 int pre=0; 82 int main() 83 { 84 freopen("in.in","r",stdin); 85 freopen("out.out","w",stdout); 86 while(inin(n)) 87 { 88 inin(m); 89 pre=0; 90 memset(head,0,sizeof(head));ed=0; 91 re(i,2,n) 92 { 93 int a,b; 94 // scanf("%d%d",&a,&b); 95 inin(a),inin(b); 96 add(a,b); 97 } 98 dfs(1); 99 xiao[0]=xiao[1]=xiao[2]=n+1; 100 for(int i=head[1];i;i=Next[i]) 101 { 102 dfsxxx(zhi[i],zhi[i]); 103 int temp=min(g[zhi[i]][0],zhi[i]); 104 if(xiao[0]>temp) 105 xiao[2]=xiao[1], 106 xiao[1]=xiao[0], 107 xiao[0]=temp; 108 else if(xiao[1]>temp) 109 xiao[2]=xiao[1], 110 xiao[1]=temp; 111 else if(xiao[2]>temp) 112 xiao[2]=temp; 113 } 114 f[3][3]=xiao[0]; 115 f[3][0]=f[0][3]=xiao[1],f[3][1]=f[1][3]=xiao[0],f[3][2]=f[2][3]=xiao[0]; 116 f[0][1]=f[1][0]=xiao[2],f[1][2]=f[2][1]=xiao[0],f[0][2]=f[2][0]=xiao[1]; 117 dfs2(1); 118 // dfs3(1); 119 dui[1]=-1; 120 re(i,1,m) 121 { 122 int a,b; 123 // scanf("%d%d",&a,&b); 124 inin(a),inin(b); 125 a=a^pre,b=b^pre; 126 if(a==0)a++;if(b==0)b++;if(a>n)a=a%n+1;if(b>n)b=b%n+1; 127 // printf("%d %d %d\n",a,b,pre); 128 if(dui[a]==dui[b]&&dui[a]!=-1){pre=1;} 129 else if(a==1) 130 if(b==1){pre=xiao[0];} 131 else 132 { 133 int now=hhh(b); 134 re(i,0,2)if(i!=now){pre=min(dp[b],xiao[i]);break;} 135 } 136 else if(b==1) 137 { 138 int now=hhh(a); 139 re(i,0,2)if(i!=now){pre=min(dp[a],xiao[i]);break;} 140 } 141 else {pre=min(min(dp[a],dp[b]),f[hhh(a)][hhh(b)]);} 142 printf("%d\n",pre); 143 } 144 } 145 return 0; 146 }