codeforces666B

Posted gaojunonly1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces666B相关的知识,希望对你有一定的参考价值。

题意:一个有N个定点M条边的有向图,dist[i][j]表示从i到j的最短距离,每条边的长度皆为1,请你给出有序的四个点a,b,c,d,使dist[a][b]+dist[b][c]+dist[c][d]最大。

思路:先用SPFA处理最短路是显然的,然后就是怎么选择点的问题,既然要和最大,那么肯定是两两个点之间的距离最大,那么我们可以预处理出每个点距离最远的点,然后只暴力中间两个点,注意预处理的时候不能用set以求方便,set常数较大会超时,还要注意不能只处理距离最远的,因为会有重复的情况,还要注意重复的情况挪点的时候,要判断size是否大于1,否则会越界。

AC程序

//库省略
using namespace std;
const int maxn=3005,INF=1e9;
int n,m;
vector<int> g[maxn];
bool vis[maxn];
int dis[maxn][maxn];
int far[maxn],len[maxn];
pii to[maxn][5],back[maxn][5];
void SPFA()

for(int i=1;i<=n;i++)

memset(vis,0,sizeof(vis));
dis[i][i]=0;
queue<int> q;
q.push(i);
while(!q.empty())

int u=q.front();
vis[u]=1;
q.pop();
for(int j=0;j<g[u].size();j++)

int v=g[u][j];
dis[i][v]=min(dis[i][v],dis[i][u]+1);
if(!vis[v])
q.push(v);




bool cmp(pii a,pii b)

return a.fi>b.fi;

void updateto(int x,int len,int id)

to[x][3].fi=len;
to[x][3].se=id;
sort(to[x],to[x]+4,cmp);

void updateback(int x,int len,int id)

back[x][3].fi=len;
back[x][3].se=id;
sort(back[x],back[x]+4,cmp);

int main()

cin>>n>>m;
for(int i=0;i<m;i++)

int x,y;
cin>>x>>y;
g[x].pb(y);

for(int i=1;i<=n;i++)

for(int j=1;j<=n;j++)

dis[i][j]=INF;


memset(len,-1,sizeof(len));
SPFA();
/*
for(int i=1;i<=n;i++)

for(int j=1;j<=n;j++)

cout<<i<<"to"<<j<<":"<<dis[i][j]<<endl;


*/
for(int i=1;i<=n;i++)

for(int j=1;j<=n;j++)

if(i==j || dis[i][j]==INF)
continue;
updateto(i,dis[i][j],j);
updateback(j,dis[i][j],i);


/*
for(int i=1;i<=n;i++)

cout<<i<<":";
for(int j=0;j<3;j++)

cout<<"(len:"<<back[i][j].fi<<" id:"<<back[i][j].se<<")";

cout<<endl;

*/
int maxm=-1;
int a1=0,a2=0,a3=0,a4=0;
for(int i=1;i<=n;i++)

for(int j=1;j<=n;j++)

if(i==j || dis[i][j]==INF || !to[j][0].se || !back[i][0].se)
continue;
//cout<<i<<" "<<j<<":";
int ans1,ans2;
int nex=0,bac=0;
int nexid=to[j][nex].se,bacid=back[i][bac].se;
//cout<<bacid<<" "<<i<<" "<<j<<" "<<nexid<<endl;

if(nexid==i)
nex++;
if(bacid==j)
bac++;
if(!to[j][nex].se || !back[i][bac].se)
continue;
nexid=to[j][nex].se;
bacid=back[i][bac].se;
int nexlen=to[j][nex].fi,baclen=back[i][bac].fi;

if(nexid==bacid)

bac++;nex++;
nexid=to[j][nex].se;
bacid=back[i][bac].se;
if(nexid==0 && bacid==0)
continue;
if(nexid!=0 && bacid!=0)

bac--;
nexlen=to[j][nex].fi;baclen=back[i][bac].fi;
ans1=nexlen+baclen;//nex


bac++;nex--;
nexlen=to[j][nex].fi;baclen=back[i][bac].fi;
ans2=nexlen+baclen;//bac


if(ans1>ans2)
bac--,nex++;
nexid=to[j][nex].se;
bacid=back[i][bac].se;

else

if(nexid==0)
nex--;
else
bac--;
nexlen=to[j][nex].fi;baclen=back[i][bac].fi;
nexid=to[j][nex].se;bacid=back[i][bac].se;
ans2=ans1=nexlen+baclen;


ans2=ans1=nexlen+baclen;
ans1+=dis[i][j];
ans2+=dis[i][j];
int ans=max(ans1,ans2);
//cout<<ans<<endl;
if(ans>maxm)

maxm=ans;
a1=bacid;
a2=i;
a3=j;
a4=nexid;



cout<<a1<<" "<<a2<<" "<<a3<<" "<<a4<<endl;
return 0;

以上是关于codeforces666B的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #524 (Div. 2) codeforces 1080A~1080F

后缀自动机 线段树合并 codeforces666E

[Codeforces 666B] World Tour

codeforces666B

codeforces666A

CodeForces - 666E: Forensic Examination (SAM 绾挎鏍戝悎骞?