#2691. 「POI2012」约会 Rendezvous

这题我简直不想说什么了,什么素质,卡常数……

“每个顶点有且仅有一条出边”,所以是一道基环树的题,首先tarjan缩点,在缩完点后的图上求a,b的LCA,如果LCA在环内,求出a,b分别对应环中的哪一个点,显然这两个点中的一个为最优解。

我一开始是在求LCA时顺便求出的a,b对应的点,这样使常数变大,虽然在LOJ和bzoj上都A了,但是在某OJ上疯狂T94,调了一下午+一晚上……

这个可以提前一边dfs预处理出来:

 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);
} for(int i=;i<=tot;i++)
if(scc[i].size()>)
for(int j=;j<scc[i].size();j++)
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=<<|;
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=;char a=getchar();
while(a<''||a>'')a=getchar();
while(a>=''&&a<=''){s=s*+a-'';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]=;
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]=;ooo=;
while(stack[top]!=x)
{
belong[stack[top]]=tot;
scc[tot].push_back(stack[top]);
sor[stack[top]]=++ooo;
vi[stack[top--]]=;
}
sor[stack[top]]=++ooo;
scc[tot].push_back(stack[top]);
belong[stack[top--]]=tot;
}
} int dep[MAXN],fa[MAXN][];
int bin[];
void dfs(int x,int ff,int de,int tr)
{
fa[x][]=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+,tr);
}
int LCA(int a,int b,int x,int y,int &xi,int &yi,int &xx,int &yy)
{
xi=yi=;xx=a;yy=b;
bool pd=;
if(dep[x]>dep[y]){swap(x,y);swap(xx,yy);pd=;}
if(dep[x]!=dep[y])
{
while(dep[x]!=dep[y]-)
for(rint i=;;i++)
if(dep[fa[y][i]]-<dep[x])
{y=fa[y][i-];yi+=bin[i-];break;}
yy=scc[y][];yy=d[yy];
y=fa[y][],yi++;
}
if(x==y)
{
if(pd){swap(xi,yi);swap(xx,yy);}
return y;
}
while(fa[x][]!=fa[y][])
for(rint i=;;i++)
if(fa[x][i]==fa[y][i])
{x=fa[x][i-],y=fa[y][i-];xi+=bin[i-],yi+=bin[i-];break;}
if(pd){swap(xi,yi);swap(x,y);}++xi,++yi;
xx=d[scc[x][]],yy=d[scc[y][]];
return fa[x][];
}
int du[MAXN];
signed main()
{
// freopen("1.in","r",stdin);
// freopen("in.txt","r",stdin); bin[]=;for(rint i=;i<;i++)bin[i]=bin[i-]<<;
n=read(),k=read();
for(rint i=;i<=n;i++){d[i]=read();add(d[i],i);}
for(rint i=;i<=n;i++)
if(!dfn[i])tarjan(i);
for(rint i=;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=;i<=tot;i++)
if(!du[i])dfs(i,,,++tr);
for(rint i=;i<;i++)
for(rint j=;j<=tot;j++)
fa[j][i]=fa[fa[j][i-]][i-];
int a,b,xi,yi,xx,yy;
int lca,t1,t2,x1,x2,y1,y2;
for(rint i=;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()==){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;
}

疯狂T94的沙雕代码

#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=<<|;
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=;char a=getchar();
while(a<''||a>'')a=getchar();
while(a>=''&&a<=''){s=s*+a-'';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]=;
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]=;ooo=;
while(stack[top]!=x)
{
belong[stack[top]]=tot;
scc[tot].push_back(stack[top]);
sor[stack[top]]=++ooo;
vi[stack[top--]]=;
}
sor[stack[top]]=++ooo;
scc[tot].push_back(stack[top]);
belong[stack[top--]]=tot;
}
} int dep[MAXN],fa[MAXN][];
int bin[];
void dfs(int x,int ff,int de,int tr)
{
fa[x][]=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+,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=;;i++)
if(dep[fa[y][i]]<dep[x])
{y=fa[y][i-];break;}
if(x==y){return y;}
while(fa[x][]!=fa[y][])
for(rint i=;;i++)
if(fa[x][i]==fa[y][i])
{x=fa[x][i-],y=fa[y][i-];break;}
return fa[x][];
}
int du[MAXN];
signed main()
{
// freopen("1.in","r",stdin);
// freopen("in.txt","r",stdin); bin[]=;for(rint i=;i<;i++)bin[i]=bin[i-]<<;
n=read(),k=read();
for(rint i=;i<=n;i++){d[i]=read();add(d[i],i);}
for(rint i=;i<=n;i++)
if(!dfn[i])tarjan(i);
for(rint i=;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=;i<=tot;i++)
if(!du[i])dfs(i,,,++tr);
for(rint i=;i<;i++)
for(rint j=;j<=tot;j++)
fa[j][i]=fa[fa[j][i-]][i-];
for(int i=;i<=tot;i++)
if(scc[i].size()>)
for(int j=;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=;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;
}

改完后的AC代码

「POI2012」约会 Rendezvous的更多相关文章

  1. 「POI2012」井 Well

    description 你要挖井,\(n\)个地面的高度可视为\(h_i\),每次操作你可以将一个\(h_i-1\),你最多可执行\(m\)次操作. 你要任选其中一个\(h_i\)挖到\(0\),问你 ...

  2. POJ1061 青蛙的约会 和 LOJ2721 「NOI2018」屠龙勇士

    青蛙的约会 Language:Default 青蛙的约会 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 133470 Accep ...

  3. 「Luogu4556」Vani有约会-雨天的尾巴

    「Luogu4556」Vani有约会-雨天的尾巴 传送门 很显然可以考虑树上差分+桶,每次更新一条链就是把这条链上的点在桶对应位置打上 \(1\) 的标记, 最后对每个点取桶中非零值的位置作为答案即可 ...

  4. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  5. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  6. JavaScript OOP 之「创建对象」

    工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...

  7. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

  8. 「JavaScript」四种跨域方式详解

    超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...

  9. 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management

    写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...

随机推荐

  1. 关于JavaScript的一些不得不知道的事儿

    1.JavaScript不区分整数和浮点数,统一用Number表示. 2.NaN这个特殊的Number与所有其他值都不相等,包括它自己: NaN===NaN; //false 唯一能判断NaN的方法是 ...

  2. 洛谷P1978 集合 [2017年6月计划 数论08]

    P1978 集合 题目描述 集合是数学中的一个概念,用通俗的话来讲就是:一大堆数在一起就构成了集合.集合有如 下的特性: •无序性:任一个集合中,每个元素的地位都是相同的,元素之间是无序的. •互异性 ...

  3. ML面试1000题系列(31-40)

    本文总结ML面试常见的问题集 转载来源:https://blog.csdn.net/v_july_v/article/details/78121924 31.下列哪个不属于CRF模型对于HMM和MEM ...

  4. 使用pip安装pymysql

    本人使用的python版本是3.6,该版本是自带有pip.可以直接通过pip工具进行安装pymysql: 第一步:找到pip.exe路径. 例如我安装的目录如下,自带的pip工具的python版本,在 ...

  5. arcgis增大缩放级别

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  6. Android——<uses-sdk>

    语法(SYNTAX): <uses-sdk android:minSdkVersion="integer" android:targetSdkVersion="in ...

  7. freemarker 取值(插值)(转)

    Java数据模型 1)基本数据类型取值 八种基本的java类型:byte.short.int.long:float,double:char:boolean 对应的封装类型:Byte.Short.Int ...

  8. windows10 中微信(UWP)版本不显示通知消息

    前言: 前段时间笔者更换了升级了WINDOWS10系统,从应用商店安装微信后,使用期间不会推送消息通知,右下角的通知栏也无法添加微信图标.搜索百度和Google后,发现很多人都是这样,这是微信(UWP ...

  9. Jeff Dean 光辉事迹

    这是Google 2007年的愚人节笑话,罗列了很多Jeff Dean的“光辉事迹”.大名鼎鼎的Jeff Dean想必不用我介绍了.……好吧,还是介绍一下,Jeff Dean是Google最早的一批员 ...

  10. 【JZOJ4895】【NOIP2016提高A组集训第16场11.15】三部曲

    =v= 因为外来的入侵,国王决定在某些城市加派士兵.所有城市初始士兵数量为0.当城市 被加派了k名士兵时.城市i的所有子城市需要被加派k+1名士兵.这些子城市的所有子城市需要被加派k+2名士兵.以此类 ...