#2691. 「POI2012」约会 Rendezvous
这题我简直不想说什么了,什么素质,卡常数……
“每个顶点有且仅有一条出边”,所以是一道基环树的题,首先tarjan缩点,在缩完点后的图上求a,b的LCA,如果LCA在环内,求出a,b分别对应环中的哪一个点,显然这两个点中的一个为最优解。
我一开始是在求LCA时顺便求出的a,b对应的点,这样使常数变大,虽然在LOJ和bzoj上都A了,但是在某OJ上疯狂T94,调了一下午+一晚上……
这个可以提前一边dfs预处理出来:
1 void dfs2(int x,int ci,int ff) 2 { 3 incir[x]=ci; 4 for(int i=f(x);i;i=n(i)) 5 if(v(i)!=ff && belong[v(i)]!=belong[x]) 6 dfs2(v(i),ci,x); 7 } 8 9 for(int i=1;i<=tot;i++) 10 if(scc[i].size()>1) 11 for(int j=0;j<scc[i].size();j++) 12 dfs2(scc[i][j],scc[i][j],d[scc[i][j]]);
感谢ooo帮忙卡常以及mikufun大佬提醒。
#include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<queue> #include<cmath> #define rint register int #define MAXN 500010 #define ma(x) memset(x,0,sizeof(x)) #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) const int L=1<<20|1; char buffer[L],*S,*T; #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++) using namespace std; struct edge { int u,v,nxt; #define u(x) ed[x].u #define v(x) ed[x].v #define n(x) ed[x].nxt #define v2(x) ed2[x].v #define n2(x) ed2[x].nxt }ed[MAXN],ed2[MAXN]; int first[MAXN],num_e; #define f(x) first[x] int first2[MAXN],num_e2; #define f2(x) first2[x] int n,k; int d[MAXN]; inline void add(rint u,rint v); inline void add2(rint u,rint v); inline void swap(rint *a,rint* b) { *a = *a ^ *b; *b = *a ^ *b; *a = *a ^ *b; } inline int read() { int s=0;char a=getchar(); while(a<'0'||a>'9')a=getchar(); while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();} return s; } int dfn[MAXN],low[MAXN],cnt; int stack[MAXN],top; bool vi[MAXN]; int tot,belong[MAXN]; vector<int> scc[MAXN]; int sor[MAXN],ooo; int intree[MAXN],tr; void tarjan(int x) { dfn[x]=++cnt;low[x]=cnt; vi[x]=1; stack[++top]=x; for(rint i=f(x);i;i=n(i)) if(!dfn[v(i)])tarjan(v(i)),low[x]=min(low[x],low[v(i)]); else if(vi[v(i)])low[x]=min(low[x],low[v(i)]); if(dfn[x]==low[x]) { tot++;vi[x]=0;ooo=0; while(stack[top]!=x) { belong[stack[top]]=tot; scc[tot].push_back(stack[top]); sor[stack[top]]=++ooo; vi[stack[top--]]=0; } sor[stack[top]]=++ooo; scc[tot].push_back(stack[top]); belong[stack[top--]]=tot; } } int dep[MAXN],fa[MAXN][21]; int bin[21]; void dfs(int x,int ff,int de,int tr) { fa[x][0]=ff;dep[x]=de;intree[x]=tr; for(rint i=f2(x);i;i=n2(i)) if(v2(i)!=ff && !dep[v2(i)]) dfs(v2(i),x,de+1,tr); } int LCA(int a,int b,int x,int y,int &xi,int &yi,int &xx,int &yy) { xi=yi=0;xx=a;yy=b; bool pd=0; if(dep[x]>dep[y]){swap(x,y);swap(xx,yy);pd=1;} if(dep[x]!=dep[y]) { while(dep[x]!=dep[y]-1) for(rint i=0;;i++) if(dep[fa[y][i]]-1<dep[x]) {y=fa[y][i-1];yi+=bin[i-1];break;} yy=scc[y][0];yy=d[yy]; y=fa[y][0],yi++; } if(x==y) { if(pd){swap(xi,yi);swap(xx,yy);} return y; } while(fa[x][0]!=fa[y][0]) for(rint i=0;;i++) if(fa[x][i]==fa[y][i]) {x=fa[x][i-1],y=fa[y][i-1];xi+=bin[i-1],yi+=bin[i-1];break;} if(pd){swap(xi,yi);swap(x,y);}++xi,++yi; xx=d[scc[x][0]],yy=d[scc[y][0]]; return fa[x][0]; } int du[MAXN]; signed main() { // freopen("1.in","r",stdin); // freopen("in.txt","r",stdin); bin[0]=1;for(rint i=1;i<20;i++)bin[i]=bin[i-1]<<1; n=read(),k=read(); for(rint i=1;i<=n;i++){d[i]=read();add(d[i],i);} for(rint i=1;i<=n;i++) if(!dfn[i])tarjan(i); for(rint i=1;i<=num_e;i++) if(belong[u(i)]!=belong[v(i)]) add2(belong[u(i)],belong[v(i)]),du[belong[v(i)]]++; for(rint i=1;i<=tot;i++) if(!du[i])dfs(i,0,1,++tr); for(rint i=1;i<20;i++) for(rint j=1;j<=tot;j++) fa[j][i]=fa[fa[j][i-1]][i-1]; int a,b,xi,yi,xx,yy; int lca,t1,t2,x1,x2,y1,y2; for(rint i=1;i<=k;i++) { a=read(),b=read(); if(intree[belong[a]]!=intree[belong[b]]){puts("-1 -1");continue;} lca=LCA(a,b,belong[a],belong[b],xi,yi,xx,yy); if(!lca){puts("-1 -1");continue;} if(scc[lca].size()==1){printf("%d %d\n",xi,yi);continue;} t1=(sor[xx]-sor[yy]+scc[belong[xx]].size()), t2=(sor[yy]-sor[xx]+scc[belong[xx]].size()); if(t1>=scc[belong[xx]].size())t1-=scc[belong[xx]].size(); if(t2>=scc[belong[xx]].size())t2-=scc[belong[xx]].size(); swap(t1,t2); x1=xi,y1=yi+t2; x2=xi+t1,y2=yi; int ma1=max(x1,y1),ma2=max(x2,y2),mi1=min(x1,y1),mi2=min(x2,y2); if(ma1!=ma2){ma1<ma2?printf("%d %d\n",x1,y1):printf("%d %d\n",x2,y2);} else if(mi1!=mi2){mi1<mi2?printf("%d %d\n",x1,y1):printf("%d %d\n",x2,y2);} else{x1>=y1?printf("%d %d\n",x1,y1):printf("%d %d\n",x2,y2);} } } inline void add(rint u,rint v) { u(++num_e)=u; v(num_e)=v; n(num_e)=f(u); f(u)=num_e; } inline void add2(rint u,rint v) { v2(++num_e2)=v; n2(num_e2)=f2(u); f2(u)=num_e2; }
#include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<queue> #include<cmath> #define rint register int #define MAXN 500010 #define ma(x) memset(x,0,sizeof(x)) #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) const int L=1<<20|1; char buffer[L],*S,*T; #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++) using namespace std; struct edge { int u,v,nxt; #define u(x) ed[x].u #define v(x) ed[x].v #define n(x) ed[x].nxt #define v2(x) ed2[x].v #define n2(x) ed2[x].nxt }ed[MAXN],ed2[MAXN]; int first[MAXN],num_e; #define f(x) first[x] int first2[MAXN],num_e2; #define f2(x) first2[x] int n,k; int d[MAXN]; inline void add(rint u,rint v); inline void add2(rint u,rint v); inline void swap(rint *a,rint* b) { *a = *a ^ *b; *b = *a ^ *b; *a = *a ^ *b; } inline int read() { int s=0;char a=getchar(); while(a<'0'||a>'9')a=getchar(); while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();} return s; } int dfn[MAXN],low[MAXN],cnt; int stack[MAXN],top; bool vi[MAXN]; int tot,belong[MAXN]; vector<int> scc[MAXN]; int sor[MAXN],ooo; int intree[MAXN],tr; int incir[MAXN],ci; void tarjan(int x) { dfn[x]=++cnt;low[x]=cnt; vi[x]=1; stack[++top]=x; for(rint i=f(x);i;i=n(i)) if(!dfn[v(i)])tarjan(v(i)),low[x]=min(low[x],low[v(i)]); else if(vi[v(i)])low[x]=min(low[x],low[v(i)]); if(dfn[x]==low[x]) { tot++;vi[x]=0;ooo=0; while(stack[top]!=x) { belong[stack[top]]=tot; scc[tot].push_back(stack[top]); sor[stack[top]]=++ooo; vi[stack[top--]]=0; } sor[stack[top]]=++ooo; scc[tot].push_back(stack[top]); belong[stack[top--]]=tot; } } int dep[MAXN],fa[MAXN][21]; int bin[21]; void dfs(int x,int ff,int de,int tr) { fa[x][0]=ff;dep[x]=de;intree[x]=tr; for(rint i=f2(x);i;i=n2(i)) if(v2(i)!=ff && !dep[v2(i)]) dfs(v2(i),x,de+1,tr); } void dfs2(int x,int ci,int ff) { incir[x]=ci; for(int i=f(x);i;i=n(i)) if(v(i)!=ff && belong[v(i)]!=belong[x]) dfs2(v(i),ci,x); } int LCA(int x,int y) { if(dep[x]>dep[y])swap(x,y); while(dep[x]!=dep[y]) for(rint i=0;;i++) if(dep[fa[y][i]]<dep[x]) {y=fa[y][i-1];break;} if(x==y){return y;} while(fa[x][0]!=fa[y][0]) for(rint i=0;;i++) if(fa[x][i]==fa[y][i]) {x=fa[x][i-1],y=fa[y][i-1];break;} return fa[x][0]; } int du[MAXN]; signed main() { // freopen("1.in","r",stdin); // freopen("in.txt","r",stdin); bin[0]=1;for(rint i=1;i<20;i++)bin[i]=bin[i-1]<<1; n=read(),k=read(); for(rint i=1;i<=n;i++){d[i]=read();add(d[i],i);} for(rint i=1;i<=n;i++) if(!dfn[i])tarjan(i); for(rint i=1;i<=num_e;i++) if(belong[u(i)]!=belong[v(i)]) add2(belong[u(i)],belong[v(i)]),du[belong[v(i)]]++; for(rint i=1;i<=tot;i++) if(!du[i])dfs(i,0,1,++tr); for(rint i=1;i<20;i++) for(rint j=1;j<=tot;j++) fa[j][i]=fa[fa[j][i-1]][i-1]; for(int i=1;i<=tot;i++) if(scc[i].size()>1) for(int j=0;j<scc[i].size();j++) dfs2(scc[i][j],scc[i][j],d[scc[i][j]]); int a,b,xi,yi,xx,yy; int lca,t1,t2,x1,x2,y1,y2; for(rint i=1;i<=k;i++) { a=read(),b=read(); if(intree[belong[a]]!=intree[belong[b]]){puts("-1 -1");continue;} if(incir[a]==incir[b]) { lca=LCA(belong[a],belong[b]); printf("%d %d\n",dep[belong[a]]-dep[lca],dep[belong[b]]-dep[lca]); continue; } else xx=incir[a],yy=incir[b],xi=dep[belong[a]]-dep[belong[incir[a]]],yi=dep[belong[b]]-dep[belong[incir[b]]]; t1=(sor[xx]-sor[yy]+scc[belong[xx]].size()), t2=(sor[yy]-sor[xx]+scc[belong[xx]].size()); if(t1>=scc[belong[xx]].size())t1-=scc[belong[xx]].size(); if(t2>=scc[belong[xx]].size())t2-=scc[belong[xx]].size(); swap(t1,t2); x1=xi,y1=yi+t2; x2=xi+t1,y2=yi; int ma1=max(x1,y1),ma2=max(x2,y2),mi1=min(x1,y1),mi2=min(x2,y2); if(ma1!=ma2){ma1<ma2?printf("%d %d\n",x1,y1):printf("%d %d\n",x2,y2);} else if(mi1!=mi2){mi1<mi2?printf("%d %d\n",x1,y1):printf("%d %d\n",x2,y2);} else{x1>=y1?printf("%d %d\n",x1,y1):printf("%d %d\n",x2,y2);} } } inline void add(rint u,rint v) { u(++num_e)=u; v(num_e)=v; n(num_e)=f(u); f(u)=num_e; } inline void add2(rint u,rint v) { v2(++num_e2)=v; n2(num_e2)=f2(u); f2(u)=num_e2; }