首页 > 其他分享 >ICPC2015(沈阳)HDU5521 建图技巧+最短路

ICPC2015(沈阳)HDU5521 建图技巧+最短路

时间:2023-06-02 18:31:45浏览次数:72  
标签:ICPC2015 int len 建图 HDU5521 集合 include block dis

Meeting

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)

Total Submission(s): 3533    Accepted Submission(s): 1136



Problem Description

Bessie and her friend Elsie decide to have a meeting. However, after Farmer John decorated his

fences they were separated into different blocks. John's farm are divided into  blocks labelled from  to .

Bessie lives in the first block while Elsie lives in the -th one. They have a map of the farm

which shows that it takes they  minutes to travel from a block in  to another block

in  where  is a set of blocks. They want to know how soon they can meet each other

and which block should be chosen to have the meeting.


Input

The first line contains an integer , the number of test cases. Then  test cases

follow.


The first line of input contains  and . . The following  lines describe the sets . Each line will contain two integers  and  firstly. Then  integer follows which are the labels of blocks in . It is guaranteed that .


Output

For each test case, if they cannot have the meeting, then output "Evil John" (without quotes) in one line.


Otherwise, output two lines. The first line contains an integer, the time it takes for they to meet.

The second line contains the numbers of blocks where they meet. If there are multiple

optional blocks, output all of them in ascending order.


Sample Input

 

 


2
5 4
1 3 1 2 3
2 2 3 4
10 2 1 5
3 3 3 4 5
3 1
1 2 1 2

 

 


Sample Output

 

 


 

  Case #1: 3

3 4

Case #2: Evil John


 


   

    Hint

   

   


   

   

In the first case, it will take Bessie 1 minute travelling to the 3rd block, and it will take Elsie 3 minutes travelling to the 3rd block. It will take Bessie 3 minutes travelling to the 4th block, and it will take Elsie 3 minutes travelling to the 4th block. In the second case, it is impossible for them to meet.



Source

2015ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)


【题意】:


有n个点,和m个集合。


每个集合里有一些点,这些点之间的距离全部为输入的ti值。


然后两个人从1和n分别出发,去任意一个点上见面,使得距离最短(题目中描述的time可以看做距离)


【体会】:


必须要说一下这个题收获颇深!


拿到题目后心里很明白,只要把图建成,跑两边最短路即可。可是图示以集合的形式给出的;


难就难在建图。


最初我是直接集合内部两两链接建图,但是边太多了!超时超内存打不了。


后来我直接不建图了,用spfa跑这个集合。


具体方法见分析。




之后去看百度的题解,哇,真是太巧妙了,还有这种建图操作。


总之是干出颇深,长见识了。


【分析】:


方法1:


用链式前向星存两个关系。


e存 点u的所在集合编号。


e2存集合i的所有元素。




跑spfa,在这两个关系上。




用len[]表示跑到集合i的最短距离。


用dis[]表示跑到点i的最短距离。




优先判断len[],如果len[]得到了更新,那么再去更新这个集合内的点的距离dis。


这种操作也是第一次尝试。


别忘了加优化inq[],标记点入队列,同一个点无需入多次队列


方法2:


看到网上的题解,这建图方法佩服。


对于每一个集合,虚拟出一个点来,让集合内所有点链接它(试着画画图)。


这些集合一定有交集,否则图不通。


然后跑n+m个点的最短路。但是每个点要先走到虚拟点,才能再走到其他点,所以跑最短路,最后再除以2,才是真实的最短路。




跑完最短路,下面的操作就水了,不啰嗦了。


【代码(方法1)】:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
const ll INF=1ll<<32;
const int MAX=1e6+5;
struct node{
    int t;
    int next;
}e[MAX*6],e2[MAX*6];
int head[100110],cnt;
void add(int u,int se)//u的所在集合se
{
    e[cnt].t=se;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
int ti[MAX],cn;//第i个集合的元素
void add2(int i,int E)//第i个集合内的元素E
{
    e2[cn].t=E;
    e2[cn].next=ti[i];
    ti[i]=cn++;
}
int T,n,m,s,u;
ll dis1[100110],disn[100110];
int t[MAX];//第i个集合的时间
ll len[MAX];
void spfa(int s,ll dis[])
{
    for(int i=0;i<=n;i++)dis[i]=INF;
    for(int i=0;i<=m;i++)len[i]=INF;
    dis[s]=0;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();q.pop();  //现在u为起点
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].t;//u在第v个集合
            if(len[v]>dis[u]+t[v])//到达集合v中的点的距离
            {
                len[v]=dis[u]+t[v];
                for(int k=ti[v];~k;k=e2[k].next)//跑第v个集合
                    if(dis[e2[k].t]>len[v])
                    {
                        dis[e2[k].t]=len[v];
                        q.push(e2[k].t);
                    }
            }
 
        }
    }
}
 
int main()
{
    scanf("%d",&T);
    for(int h=1;h<=T;h++)
    {
        scanf("%d%d",&n,&m);
        cn=cnt=0;
        for(int i=0;i<=n;i++)ti[i]=head[i]=-1;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&t[i],&s);
            while(s--)
            {
                scanf("%d",&u);
                add(u,i);//u在第i个集合中
                add2(i,u);//第i个集合中有u
            }
        }
        spfa(1,dis1);
        spfa(n,disn);
        ll flag=INF;
        for(int i=1;i<=n;i++)
        {
            dis1[i]=max(dis1[i],disn[i]);
            flag=min(flag,dis1[i]);
        }
        if(flag==INF){
            printf("Case #%d: Evil John\n",h);
            continue;
        }
        printf("Case #%d: %d\n",h,flag);
        int ans[100100],top=0;
        for(int i=1;i<=n;i++)
            if(dis1[i]==flag)
                ans[top++]=i;
        for(int i=0;i<top-1;i++)
            printf("%d ",ans[i]);
        printf("%d\n",ans[top-1]);
    }
    return 0;
}



【代码(方法2)】:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
const ll INF=1ll<<45;
const int MAX=1e6+5;
struct node{
    int t,time;
    int next;
}e[MAX*2];
int head[MAX<<1],cnt;
void add(int u,int v,int time)
{
    e[cnt]=node{v,time,head[u]};
    head[u]=cnt++;
}
int T,n,m,time,s,u;
ll dis1[MAX<<1],disn[MAX<<1];
bool inq[MAX<<1];
void spfa(int s,ll dis[])
{
    for(int i=0;i<=n+m;i++)dis[i]=INF<<1;
    memset(inq,0,sizeof(inq));
    dis[s]=0;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        inq[u]=0;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].t;
            if(dis[v]>dis[u]+e[i].time)
            {
                dis[v]=dis[u]+e[i].time;
                if(!inq[v])
                {
                    inq[v]=1;
                    q.push(v);
                }
            }
        }
    }
}
 
int main()
{
    scanf("%d",&T);
    for(int h=1;h<=T;h++)
    {
        scanf("%d%d",&n,&m);
        cnt=0;
        for(int i=0;i<=n+m;i++)head[i]=-1;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&time,&s);
            while(s--)
            {
                scanf("%d",&u);
                add(u,i+n,time);
                add(i+n,u,time);
            }
        }
        spfa(1,dis1);
        spfa(n,disn);
        ll flag=INF;
        for(int i=1;i<=n;i++)
        {
            dis1[i]=max(dis1[i]/2,disn[i]/2);
            flag=min(flag,dis1[i]);
        }
        if(flag==INF){
            printf("Case #%d: Evil John\n",h);
            continue;
        }
        printf("Case #%d: %d\n",h,flag);
        int ans[100100],top=0;
        for(int i=1;i<=n;i++)
            if(dis1[i]==flag)
                ans[top++]=i;
        for(int i=0;i<top-1;i++)
            printf("%d ",ans[i]);
        printf("%d\n",ans[top-1]);
    }
	return 0;
}



标签:ICPC2015,int,len,建图,HDU5521,集合,include,block,dis
From: https://blog.51cto.com/u_16125110/6404566

相关文章

  • picgo+github搭建图床,配合typora使用
    picgo下载地址:https://github.com/Molunerfinn/PicGo/releases创建一个仓库,老的也行分支的话看看仓库里的分支是什么就填写什么token的设置typroa整合......
  • 激光建图、定位学习资源整理
    自用,侵删知乎:https://zhuanlan.zhihu.com/p/113616755github:https://github.com/Little-Potato-1990/localization_in_auto_drivinggitee:https://gitee.com/suyunzzz/learn_localization_in_auto_drivinghttps://github.com/suyunzzz/sensor-fusion-for-localization-and-mappi......
  • 使用ORBSLAM2进行kineticV2稠密建图,实时转octomap建图以及导航
    决定总结最近一个月的工作,这个月在orbslam2的基础上,使用kineticV2完成了稠密点云地图的重建,实现了点云的回环,并使用octomap转换成实时的八叉树地图,导航部分已经有了思路,打算下个月所一个基于octomap的航迹生成能用在视觉的导航上。一、传感器和依赖包安装PC性能:Dellxps13内存16GB......
  • 基于机器人自主移动实现SLAM建图
    博客地址:https://www.cnblogs.com/zylyehuo/基于[移动机器人运动规划及运动仿真],详见之前的博客移动机器人运动规划及运动仿真-zylyehuo-博客园参考链接Autolabor-ROS机器人入门课程《ROS理论与实践》环境配置ubuntu18.04成果图step1:编写launch文件......
  • 基于Gazebo搭建移动机器人,并结合SLAM系统完成定位和建图仿真
    博客地址:https://www.cnblogs.com/zylyehuo/gazebo小车模型创建及仿真详见之前博客gazebo小车模型(附带仿真环境)-zylyehuo-博客园gazebo+rviz仿真-zylyehuo-博客园参考链接Autolabor-ROS机器人入门课程《ROS理论与实践》成果图step1:准备工作安装必要......
  • 激光SLAM之激光雷达+IMU建图 , 工程化落地项目,涉及激光雷达+imu 多传感器融合建图,加工
    激光SLAM之激光雷达+IMU建图,工程化落地项目,涉及激光雷达+imu多传感器融合建图,加工程应用角度的代码优化,从数据接收到闭环检测到图优化,非常完整。该商品与本人发布的“激光SLAM之多传感器融合定位”是可以组合使用的。该项目价格会比其他项目高的原因主要是在于这是真正......
  • Acwing 3728-城市通电 / 最小生成树,建图,超级源点
    AcWing3728.城市通电做出来就凭之前的一句感悟:把每个动态选择变为与超级源点连的一条边,把这条边加入图里面跑最小生成树就相当于考虑了每个动态选择......
  • 【模板】逆单源最短(反向建图) + spfa
    题目要求:不仅要求单源最短路径,还要求其余点到该点的最短路径做法:建立反图求逆单源最短路径,至于单源最短路径选择合适于题目即可参考题目1#include<iostream>2#include<queue>3#include<cstring>45usingnamespacestd;67typedeflonglongLL;8typ......
  • AcWing3305 -- 建图
    1.题目描述给定我们一些初始作物,和作物之间杂交的规则(作物\(a\)和作物\(b\)杂交产生种子\(c\),花费作物\(a\)和作物\(b\)成熟时间的最大值),让我们求,某个作物\(T......
  • 常见网络流建图
    梳理一些常见的网络流建图模型。disclaimer:以下名词,模型皆本人所造,不保证合理性及正确性。选择式例题:LuoguP3254建立\(\{A_i\}\)表示选择对象,\(\{B_j\}\)表示被选......