zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    	for (int i=1;i<=4;i++) printf("%d ",aw[i]);
    	return 0;
    }
    
    转载需注明出处。
  • 相关阅读:
    hdu_5961_传递(bitset)
    hdu_5963_朋友(找规律)
    hdu_5968_异或密码(预处理+二分)
    hdu_5969_最大的位或(贪心)
    hdu_5965_扫雷(递推)
    hdu_5950_Recursive sequence(矩阵快速幂)
    hdu_5286_wyh2000 and sequence(分块)
    [BZOJ1951][SDOI2005]古代猪文(数论好题)
    [BZOJ2659][WC2012]算不出的算式(几何)
    [BZOJ 2656][ZJOI2012]数列(递归+高精度)
  • 原文地址:https://www.cnblogs.com/jz929/p/11817547.html
Copyright © 2011-2022 走看看