题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5521

学习菊苣的博客,只粘链接,不粘题目描述了。

题目大意就是一个人从1开始走,一个人从n开始走。让最后相遇的时间最短。

题目就是个最短路,不过唯一不同的是,题目图的描述方式比较特别。

从规模上来看,想把这张图描述成邻接矩阵或者邻接表是不可能的。

必然只能按照题目要求的意思来存。

于是第一步存图的方式,我采用了两个vector数组,(当然此处可以使用链式前向星),一个存了和点相关的集合有哪些in[],即这个点包含在哪些集合里面;一个存了集合里面有哪些点edge[]。

然后就是跑两遍最短路了,这里我采用了优先队列的spfa(貌似就是优先队列的dijikstra)。

不过直接这样上去T了好多发。

然后考虑到用了优先队列后,相当于优化了这个dp的过程,让每个点只需要遍历一次。那么,自然而然的,如果i遍历了集合s里面的所有点,自然集合s也只需要遍历一次。加了这一个剪枝就能AC了。由于遍历集合的时候,不是按照从最小权值集合开始的,所以这里没有对队列里面的元素进行判重,不过影响不是很大。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#include <queue>
#include <vector>
#define LL long long using namespace std; struct node
{
int id, val;
bool operator<(const node x) const
{
return val>x.val;
}
};
const int maxN = ;
const int maxM = ;
int n, m;
vector<int> in[maxN];
int dis[maxM];
vector<int> edge[maxM];
LL p[][maxN];
bool vis[maxM]; void input()
{
scanf("%d%d", &n, &m);
int t, s, k;
for (int i = ; i < m; ++i)
{
scanf("%d%d", &t, &s);
dis[i] = t;
for (int j = ; j < s; ++j)
{
scanf("%d", &k);
in[k].push_back(i);
edge[i].push_back(k);
}
}
memset(p, -, sizeof(p));
} void spfa(int from, int x)
{
memset(vis, false, sizeof(vis));
priority_queue<node> q;
node k, t;
int w, u, v;
k.id = from;
k.val = ;
q.push(k);
p[x][from] = ;
while (!q.empty())
{
k = q.top();
q.pop();
u = k.id;
for (int i = ; i < in[u].size(); ++i)
{
w = in[u][i];
if (vis[w]) continue;
for (int j = ; j < edge[w].size(); ++j)
{
v = edge[w][j];
if (u == v) continue;
if (p[x][v] == - || p[x][v] > p[x][u]+dis[w])
{
p[x][v] = p[x][u]+dis[w];
t.id = v;
t.val = p[x][v];
q.push(t);
}
}
vis[w] = true;
}
}
} LL myMin(LL x, LL y)
{
if (x == -) return y;
else return min(x, y);
} void work()
{
spfa(, );
spfa(n, );
LL mi = -;
for (int i = ; i <= n; ++i)
if (p[][i] != - && p[][i] != -)
mi = myMin(mi, max(p[][i], p[][i]));
if (mi == -)
{
printf("Evil John\n");
return;
}
printf("%d\n", mi);
bool flag = false;
for (int i = ; i <= n; ++i)
if (p[][i] != - && p[][i] != - && mi == max(p[][i], p[][i]))
{
if (flag) printf(" ");
printf("%d", i);
flag = true;
}
printf("\n");
} void clss()
{
for (int i = ; i < m; ++i)
edge[i].clear();
for (int i = ; i <= n; ++i)
in[i].clear();
} int main()
{
//freopen("test.in", "r", stdin);
int T;
scanf("%d", &T);
for (int times = ; times < T; ++times)
{
printf("Case #%d: ", times+);
input();
work();
clss();
}
return ;
}

ACM学习历程—HDU5521 Meeting(图论)的更多相关文章

  1. 完成了C++作业,本博客现在开始全面记录acm学习历程,真正的acm之路,现在开始

    以下以目前遇到题目开始记录,按发布时间排序 ACM之递推递归 ACM之数学题 拓扑排序 ACM之最短路径做题笔记与记录 STL学习笔记不(定期更新) 八皇后问题解题报告

  2. ACM学习历程—HDU 5512 Pagodas(数学)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5512 学习菊苣的博客,只粘链接,不粘题目描述了. 题目大意就是给了初始的集合{a, b},然后取集合里 ...

  3. ACM学习历程—HDU2476 String painter(动态规划)

    http://acm.hdu.edu.cn/showproblem.php?pid=2476 题目大意是给定一个起始串和一个目标串,然后每次可以将某一段区间染成一种字符,问从起始串到目标串最少需要染多 ...

  4. ACM学习历程—HDU5700 区间交(树状数组 && 前缀和 && 排序)

    http://acm.hdu.edu.cn/showproblem.php?pid=5700 这是这次百度之星初赛2B的第五题.省赛回来看了一下,有这样一个思路:对于所有的区间排序,按左值排序. 然后 ...

  5. ACM学习历程—HDU5701 中位数计数(中位数 && 计数排序)

    http://acm.hdu.edu.cn/showproblem.php?pid=5701 这是这次百度之星初赛2B的第六题.之前白山云做过类似的题,省赛完回来,我看了一下大概就有这样的思路:首先枚 ...

  6. ACM学习历程—HDU5696 区间的价值(分治 && RMQ && 线段树 && 动态规划)

    http://acm.hdu.edu.cn/showproblem.php?pid=5696 这是这次百度之星初赛2B的第一题,但是由于正好打省赛,于是便错过了.加上2A的时候差了一题,当时有思路,但 ...

  7. ACM学习历程—HDU5668 Circle(数论)

    http://acm.hdu.edu.cn/showproblem.php?pid=5668 这题的话,假设每次报x个,那么可以模拟一遍, 假设第i个出局的是a[i],那么从第i-1个出局的人后,重新 ...

  8. ACM学习历程—HDU5667 Sequence(数论 && 矩阵乘法 && 快速幂)

    http://acm.hdu.edu.cn/showproblem.php?pid=5667 这题的关键是处理指数,因为最后结果是a^t这种的,主要是如何计算t. 发现t是一个递推式,t(n) = c ...

  9. ACM学习历程—HDU5666 Segment(数论)

    http://acm.hdu.edu.cn/showproblem.php?pid=5666 这题的关键是q为质数,不妨设线段上点(x0, y0),则x0+y0=q. 那么直线方程则为y = y0/x ...

随机推荐

  1. 下周要搞大事情(ASP.NET Core & WebForms)!

    下周要搞大事情(ASP.NET Core & WebForms)!

  2. 【BZOJ4548】小奇的糖果 set(链表)+树状数组

    [BZOJ4548]小奇的糖果 Description 有 N 个彩色糖果在平面上.小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果.求出最多能够拾起多少糖果,使得获得的糖果并不包含所有的 ...

  3. C - Common Subsequence

    C - Common Subsequence Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I ...

  4. 洛谷 P2051 [SDOI2009]学校食堂

    传送门- 题目分析:首先,我们先看看做菜时间的运算机制.$(A~\texttt{or}~B)-(A~\texttt{and}~B)$这个试子看起来有点复杂(因为我太菜了),仔细想想,是不是可以转化为$ ...

  5. spring 注入属性

    一.注入对象类型的数据 1.配置文件 User类与UserService类均需要创建对象.所以都配置其相应的bean类,另外user需作为userService的属性注入,所以userService需 ...

  6. linux c编程:进程控制(三)_exec函数

    fork()函数通过系统调用创建一个与原来进程(父进程)几乎完全相同的进程(子进程是父进程的副本,它将获得父进程数据空间.堆.栈等资源的副本.注意,子进程持有的是上述存储空间的“副本”,这意味着父子进 ...

  7. java基础入门之九九乘法表

    /* 自学java 九九乘法表 Power by Stuart Date: 2015.4.23 */public class Math { public static void main (Strin ...

  8. linux mount一个硬盘

    我们在使用linux的情况下,难免有时会需要增加一块硬盘,在windows下增加硬盘很简单,所有的操作都是有画面.linux下增加一块硬盘,并且让这块硬盘可以正常的使用,所有的操作都在字符命令行的方式 ...

  9. 《程序员代码面试指南》第一章 栈和队列 最大值减去最小值小于或等于num的数量

    题目 给定整数数组arr和整数num,共返回多少的数组满足如下情况 max(arr[i...j]) - min(arr[i...j]) <= num max(arr[i...j])表示数组arr ...

  10. 【Flask】query可用参数

    ### query可用参数:1. 模型对象.指定查找这个模型中所有的对象.2. 模型中的属性.可以指定只查找某个模型的其中几个属性.3. 聚合函数. * func.count:统计行的数量. * fu ...