jzoj 4671. 【NOIP2016提高A组模拟7.20】World Tour

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要旅游的路线。

Sample Input

8 9
1 2
2 3
3 4
4 1
4 5
5 6
6 7
7 8
8 5

Sample Output

2 1 8 7

d(2,1)=3,d(1,8)=7,d(8,7)=3,总共的距离等于13

Data Constraint

对于10% n<=10
对于20% n<=100
对于 30% n<=1000
对于100% n<=3000

Solution

这题看了看时间5000ms,决定暴力一点了。。。
我们对于a,b,c,d
只需要先求出两两点之间的最短距离(顺着的和逆着的都要求),然后枚举b,c,用逆着的b的前三大的与顺着的c的前三大的匹配,当a,b,c,d都不相等的话与ans比较即可。
PS:顺着表示按照有向边的方向加边,逆着表示按照有向边相反的方向加边。

Code

#include<cstdio>
#include<cstring>
#define N 3010
using namespace std;
struct node{int v,fr;}e[N<<1],g[N<<1];
struct hug
{
	int x,dis;
	void clean() {x=dis=0;}
};
struct Max
{
	hug a[4];
	void clean() {a[1].clean(); a[2].clean(); a[3].clean();}
}f[N],f1[N],t;
int n,m,tail[N],head[N],d[N][N],dd[N][N];
int tot=0,cnt=0,ans=0,aw[5],b[5],now,ff[N<<6];
bool bz[N];

inline int read()
{
	int x=0; char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

inline void add(int u,int v) {e[++cnt]=(node){v,tail[u]}; tail[u]=cnt;}

inline void add1(int u,int v) {g[++tot]=(node){v,head[u]}; head[u]=tot;}

void bfs(int x)
{
	int l=0,r=1;ff[1]=x;d[x][x]=0;
	while (l++<r)
	{
		for (int p=tail[ff[l]],v;p;p=e[p].fr)
		{
			v=e[p].v;
			if (d[x][ff[l]]+1<d[x][v])
			{
				d[x][v]=d[x][ff[l]]+1;
				if (!bz[v]) ff[++r]=v,bz[v]=1;
			}
		}
		bz[ff[l]]=0;
	}
	for (int i=1;i<=n;i++)
	{
		if (d[x][i]==1010580540) d[x][i]=-d[x][i];
		if (d[x][i]>f[x].a[1].dis) f[x].a[3]=f[x].a[2],f[x].a[2]=f[x].a[1],f[x].a[1]=(hug){i,d[x][i]};
		else if (d[x][i]>f[x].a[2].dis) f[x].a[3]=f[x].a[2],f[x].a[2]=(hug){i,d[x][i]};
		else if (d[x][i]>f[x].a[3].dis) f[x].a[3]=(hug){i,d[x][i]};
	}
}

void bfs1(int x)
{
	int l=0,r=1;ff[1]=x;dd[x][x]=0;
	while (l++<r)
	{
		for (int p=head[ff[l]],v;p;p=g[p].fr)
		{
			v=g[p].v;
			if (dd[x][ff[l]]+1<dd[x][v])
			{
				dd[x][v]=dd[x][ff[l]]+1;
				if (!bz[v]) ff[++r]=v,bz[v]=1;
			}
		}
		bz[ff[l]]=0;
	}
	for (int i=1;i<=n;i++)
	{
		if (dd[x][i]==1010580540) dd[x][i]=-dd[x][i];
		if (dd[x][i]>f1[x].a[1].dis) f1[x].a[3]=f1[x].a[2],f1[x].a[2]=f1[x].a[1],f1[x].a[1]=(hug){i,dd[x][i]};
		else if (dd[x][i]>f1[x].a[2].dis) f1[x].a[3]=f1[x].a[2],f1[x].a[2]=(hug){i,dd[x][i]};
		else if (dd[x][i]>f1[x].a[3].dis) f1[x].a[3]=(hug){i,dd[x][i]};
	}
}

bool check()
{
	if (b[1]==b[3]) return 1;
	if (b[1]==b[4]) return 1;
	if (b[4]==b[2]) return 1;
	return 0;
}

int main()
{
	freopen("World Tour.in","r",stdin);
//	freopen("World Tour.out","w",stdout);
	n=read(),m=read();
	for (int i=1,u,v;i<=m;i++)
		u=read(),v=read(),add(u,v),add1(v,u);
	memset(d,60,sizeof(d));
	memset(dd,60,sizeof(dd));
	for (int i=1;i<=n;i++) bfs(i),bfs1(i);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++)
		{
			if (i==j || d[i][j]==1010580540) continue;
			b[2]=i,b[3]=j;
			for (int k=1;k<=3;k++)
				for (int l=1;l<=3;l++)
				{
					b[1]=f1[i].a[k].x,b[4]=f[j].a[l].x;
					if (check()) continue;
					if (d[i][j]+f1[i].a[k].dis+f[j].a[l].dis>ans)
					{
						ans=d[i][j]+f1[i].a[k].dis+f[j].a[l].dis;
						memcpy(aw,b,sizeof(b));
					}
				}
		}
//	printf("%d\n",ans);
	for (int i=1;i<=4;i++) printf("%d ",aw[i]);
	return 0;
}
posted @ 2019-03-23 16:40  jz929  阅读(124)  评论(0编辑  收藏  举报