Codeforces 666B. World Tour 解题报告
传送门
题意:一个有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;
}