题目
Description
Cicasso是一个著名的雕塑家。
现在他想去城市之间旅游,他是一个聪明的人,所以从一个城市到另一个城市他只会走最短路。他想游览全国的风景,所以他想走的路的总长度尽量长,但是经费有限,他只能去四个城市,而且这四个城市不能重复(在途中经过的城市不计算,例如 ,他要去的四个城市有上标,[1, 5, 2, 4],这样是合法的)
注意,道路是单向路,并且距离都为1。
Input
在第一行有两个整数n和m(4<=n<=3000,3<=m<=5000),n代表城市数,m代表单向边的数量
接下来m行有两个整数ui,vi(ui,vi<=n)——代表一条从ui到vi的单向边,注意ui和vi可能相同,并且同两个城市之间可能有多条边
Output
输出四个整数,代表Cicasso要旅游的路线。
解题思路
假如四个 不同的城市为 a,b,c,d,对于每一个城市先跑一个 BFS,找出它最短路到达最
远的 3 个点,然后枚举 b,c,然后再枚举 b,c 的这 3 个点,(a,b,c,d 不能相同),找出
最大的即可。
代码80分
#include<cstdio>
#include<string>
#include<cstring>
#include<queue>
#define rr register
#define rep(i,x,y) for (register int i=x;i<=y;i++)
using namespace std;
const int N=3010,M=5010;
struct node{int y,z,next;}a[M];
int head[N],n,m,tot,root,d[N],t[N][N]; bool v[N];
int g[N][2][2],a1,a2,a3,a4,ans;
priority_queue<pair<int,int> >q;
inline int read()
{
int p=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) p=(p<<3)+(p<<1)+c-48,c=getchar();
return p;
}
void add(int x,int y,int z){a[++tot]=(node){y,z,head[x]}; head[x]=tot;}
void dijkstra(){
memset(d,0x3f,sizeof(d));
memset(v,0,sizeof(v));
d[root]=0; q.push(make_pair(0,root));
while (q.size()){
int x=q.top().second; q.pop();
if (v[x]) continue; v[x]=1;
for (rr int i=head[x];i;i=a[i].next){
int y=a[i].y,z=a[i].z;
if (d[y]>d[x]+z) d[y]=d[x]+z,q.push(make_pair(-d[y],y));
}
}
}
bool check(int x,int y,int q,int w){if (x==y||x==q||x==w||y==q||y==w||q==w) return 0; return 1; }
int main()
{
n=read(),m=read();
for (rr int i=1;i<=m;i++){
int x=read(),y=read();
add(x,y,1);
}
for (root=1;root<=n;root++) {
dijkstra();
rep(i,1,n) t[root][i]=(d[i]!=0x3f3f3f3f)?d[i]:-2147483647;
}
rep(i,1,n) rep(j,1,n) {
if (t[i][j]>t[i][g[i][0][0]]) g[i][1][0]=g[i][0][0],g[i][0][0]=j;
else if (t[i][j]>t[i][g[i][1][0]]) g[i][1][0]=j;
if (t[i][j]>t[g[j][0][1]][j]) g[j][1][1]=g[j][0][1],g[j][0][1]=i;
else if (t[i][j]>t[g[j][1][1]][j]) g[j][1][1]=i;
}
rep(i,1,n) rep(j,1,n) if (i!=j)
if (g[i][0][1]==g[j][0][1]){
if (t[g[i][1][1]][i]>t[j][g[j][1][0]]) {
if (t[g[i][1][1]][i]+t[i][j]+t[j][g[j][0][0]]>ans&&check(g[i][1][1],i,j,g[j][0][0])) {
ans=t[g[i][1][1]][i]+t[i][j]+t[j][g[j][0][0]];
a1=g[i][1][1],a2=i,a3=j,a4=g[j][0][0];
}
} else {
if (t[g[i][0][1]][i]+t[i][j]+t[j][g[j][1][0]]>ans&&check(g[i][0][1],i,j,g[j][1][0])) {
ans=t[g[i][0][0]][i]+t[i][j]+t[j][g[j][1][0]];
a1=g[i][0][1],a2=i,a3=j,a4=g[j][1][0];
}
}
} else {
if (t[g[i][0][1]][i]+t[i][j]+t[j][g[j][0][0]]>ans&&check(g[i][0][1],i,j,g[j][0][0])) {
ans=t[g[i][0][1]][i]+t[i][j]+t[j][g[j][0][0]];
a1=g[i][0][1],a2=i,a3=j,a4=g[j][0][0];
}
}
printf("%d %d %d %d",a1,a2,a3,a4);
}
100分
//以下代码巨丑,请见谅QWQ
#include <queue>
#include <cstdio>
#include <iostream>
#include <cstring>
#define mp make_pair
using namespace std;
const int N=3010;
const int M=5010;
const int Inf=1e9;
int n,m,x,y,tot,ans,a,b,c,d;
int head[N],dis[N][N],maxn[N][3][3],maxx[N][3][3];
bool vis[N];
struct edge
{
int next,to;
}e[M];
void add(int from,int to)
{
e[++tot].to=to;
e[tot].next=head[from];
head[from]=tot;
}
void dij(int S) //求最短路
{
memset(vis,0,sizeof(vis));
priority_queue<pair<int,int> > q;
q.push(mp(0,S));
dis[S][S]=0;
vis[S]=1;
while (q.size())
{
int u=q.top().second;
q.pop();
for (int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
if (dis[S][v]>dis[S][u]+1)
{
dis[S][v]=dis[S][u]+1;
if (!vis[v])
{
q.push(mp(-dis[S][v],v));
vis[v]=1;
}
}
}
}
}
bool check(int x1,int x2,int x3,int x4) //判断四个数字是否互不相同
{
if (x1==x2) return 0;
if (x1==x3) return 0;
if (x1==x4) return 0;
if (x2==x3) return 0;
if (x2==x4) return 0;
if (x3==x4) return 0;
return 1;
}
int main()
{
memset(dis,0x3f3f3f3f,sizeof(dis));
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
}
for (int i=1;i<=n;i++)
dij(i);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (dis[i][j]<Inf)
{
if (dis[i][j]>maxn[i][1][1]) //预处理出最长、次长路径
{
maxn[i][1][2]=maxn[i][1][1];
maxx[i][1][2]=maxx[i][1][1];
maxn[i][1][1]=dis[i][j];
maxx[i][1][1]=j;
}
else if (dis[i][j]>maxn[i][1][2])
{
maxn[i][1][2]=dis[i][j];
maxx[i][1][2]=j;
}
if (dis[i][j]>maxn[j][2][1])
{
maxn[j][2][2]=maxn[j][2][1];
maxx[j][2][2]=maxx[j][2][1];
maxn[j][2][1]=dis[i][j];
maxx[j][2][1]=i;
}
else if (dis[i][j]>maxn[i][2][2])
{
maxn[j][2][2]=dis[i][j];
maxx[j][2][2]=i;
}
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
if (i==j) continue;
if (dis[i][j]<Inf&&dis[i][j]+maxn[i][2][1]+maxn[j][1][1]>ans&&check(maxx[i][2][1],maxx[j][1][1],i,j))
{
ans=dis[i][j]+maxn[i][2][1]+maxn[j][1][1];
d=maxx[j][1][1]; c=j;
b=i; a=maxx[i][2][1];
}
if (dis[i][j]<Inf&&dis[i][j]+maxn[i][2][2]+maxn[j][1][1]>ans&&check(maxx[i][2][2],maxx[j][1][1],i,j))
{
ans=dis[i][j]+maxn[i][2][2]+maxn[j][1][1];
d=maxx[j][1][1]; c=j;
b=i; a=maxx[i][2][2];
}
if (dis[i][j]<Inf&&dis[i][j]+maxn[i][2][1]+maxn[j][1][2]>ans&&check(maxx[i][2][1],maxx[j][1][2],i,j))
{
ans=dis[i][j]+maxn[i][2][1]+maxn[j][1][2];
d=maxx[j][1][2]; c=j;
b=i; a=maxx[i][2][1];
}
}
printf("%d %d %d %d",a,b,c,d);
return 0;
}