ACM/ICPC 之 SPFA练习两道(ZOJ3088-ZOJ3103)
两道题都需要进行双向SPFA,比范例复杂,代码也较长,其中第二题应该可以用DFS或者BFS做,如果用DFS可能需要的剪枝较多。
ZOJ3088-Easter Holydays
//利用SPFA找出下降最长路径和上升最短路径,输出最大的比值和回路路径
//Time:0Ms Memory:328K
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std; #define MAX 1005
#define INF 0x3f3f3f3f struct Edge {
int u, w, next;
Edge(){}
Edge(int uu,int ww,int nn):u(uu),w(ww),next(nn){}
}eu[MAX], ed[MAX]; //up-down int n, m, k;
int hu[MAX], hd[MAX]; //邻接表头位置
int pu[MAX], pd[MAX]; //路径
int du[MAX], dd[MAX]; //最短路长
int tu[MAX], td[MAX]; //临时路径
bool v[MAX]; //上升最短路径
void spfa_u(int x)
{
memset(du, INF, sizeof(du));
memset(pu, -1, sizeof(pu));
memset(v, false, sizeof(v));
du[x] = 0;
queue<int> q;
q.push(x); pu[x] = x;
while (!q.empty()) {
int cur = q.front();
q.pop(); v[cur] = false;
for (int i = hu[cur]; i != -1; i = eu[i].next)
{
int u = eu[i].u, w = eu[i].w;
if (du[u] > du[cur] + w)
{
du[u] = du[cur] + w;
pu[u] = cur;
if (!v[u]) {
v[u] = true; q.push(u);
}
}
}
}
} //SPFA-下降最长路径
void spfa_d(int x)
{
memset(dd, -1, sizeof(dd));
memset(pd, -1, sizeof(pd));
memset(v, false, sizeof(v));
dd[x] = 0;
queue<int> q;
q.push(x); pd[x] = x;
while (!q.empty()) {
int cur = q.front();
q.pop(); v[cur] = false;
for (int i = hd[cur]; i != -1; i = ed[i].next)
{
int u = ed[i].u, w = ed[i].w;
if (dd[u] < dd[cur] + w)
{
dd[u] = dd[cur] + w;
pd[u] = cur;
if (!v[u]) {
v[u] = true; q.push(u);
}
}
}
}
} void path_u(int x)
{
if (tu[x] != x) path_u(tu[x]);
printf("%d ", x);
} void path_d(int x)
{
int i;
for (i = td[x]; i != td[i]; i = td[i])
printf("%d ", i);
printf("%d\n", i);
} int main()
{
int T;
scanf("%d", &T);
while (T--)
{
memset(hu, -1, sizeof(hu));
memset(hd, -1, sizeof(hd));
scanf("%d%d%d", &n, &m, &k);
int a, b, w;
for (int i = 0; i < m; i++)
{
scanf("%d%d%d", &a, &b, &w);
ed[i] = Edge(a, w, hd[b]); //反向建图
hd[b] = i;
}
for (int i = 0; i < k; i++)
{
scanf("%d%d%d", &a, &b, &w);
eu[i] = Edge(b, w, hu[a]); //正向建图
hu[a] = i;
} double rate = 0;
int tmp = -1;
for (int i = 1; i <= n; i++)
{
spfa_u(i); spfa_d(i);
for (int j = 1; j <= n; j++)
{
if (i == j || du[j] == INF) continue;
if (rate < 1.0 * dd[j] / du[j]) {
rate = 1.0 * dd[j] / du[j];
tmp = j;
memcpy(tu, pu, (n+1)*sizeof(int));
memcpy(td, pd, (n+1)*sizeof(int));
}
}
}
path_u(tmp); path_d(tmp);
printf("%.3f\n", rate);
}
return 0;
}
ZOJ3103-Cliff Climbing
//需要理清题意,比较复杂,建立双向邻接表,并须计算双向最短路
//第一次边表设大了MLE了...考虑最大边数 < n*18个,因此设为MAX*18
//Time:190Ms Memory:1152K
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std; #define MAXW 32
#define MAXH 62
#define MAX MAXW*MAXH
#define INF 0x3f3f3f3f
#define IN_RANGE(x,y) (x >= 0 && x < H && y >= 0 && y < W) struct Edge {
int u, w, next;
Edge() {}
Edge(int uu, int ww, int nn) :u(uu), w(ww), next(nn) {}
}e[2][MAX*18]; //0:左脚点 1::右脚点 int W, H, n;
int board[MAX];
int h[2][MAX], le[2];
int d[2][MAX]; //双向最短距离
bool v[MAX]; int mov0[9][2] = { { 0, 1 },{0, 2 },{0, 3 },{-1, 1 },{ -1, 2 },{ -2, 1 },{ 1, 1 },{ 1, 2 },{ 2, 1 } }; //左脚踩住,右脚移动位置
int mov1[9][2] = { { 0, -1},{0, -2},{0, -3},{-1, -1}, {-1, -2}, {-2, -1}, {1, -1}, {1, -2}, {2, -1} }; //右脚踩住,左脚移动位置 void spfa(int x)
{
memset(v, false, sizeof(v));
memset(d, INF, sizeof(d));
queue<int> q;
q.push(x); d[0][x] = d[1][x] = 0;
while (!q.empty()) {
int cur = q.front();
q.pop(); v[cur] = false;
for (int k = 0; k < 2; k++) //双向最短路
for (int i = h[k][cur]; i != -1; i = e[k][i].next)
{
int u = e[k][i].u;
int w = e[k][i].w;
if (d[!k][u] > d[k][cur] + w) //交叉影响
{
d[!k][u] = d[k][cur] + w;
if (!v[u]) {
v[u] = true; q.push(u);
}
} }
}
} int main()
{
while (scanf("%d%d", &W, &H), W && H)
{
char s[3];
n = W*H;
memset(h, -1, sizeof(h));
//一维序列表示各点
for (int i = 0; i < n; i++)
{
scanf("%s", s);
if (s[0] == 'S' || s[0] == 'T') board[i] = 0;
else if (s[0] == 'X') board[i] = INF;
else board[i] = s[0] - '0';
} //构建邻接表
le[0] = le[1] = 0;
for (int i = 0; i < n; i++)
{
if ((i < W && board[i] == 0) || board[i] == INF) continue;
for (int j = 0; j < 9; j++)
{
int x = i / W, y = i % W; //计算行与列
int x0 = x + mov0[j][0], y0 = y + mov0[j][1];
int x1 = x + mov1[j][0], y1 = y + mov1[j][1];
int n0 = x0*W + y0, n1 = x1*W + y1;
if (IN_RANGE(x0,y0) && board[n0] != INF) {
e[0][le[0]] = Edge(n0, board[n0], h[0][i]);
h[0][i] = le[0]++;
}
if (IN_RANGE(x1,y1) && board[n1] != INF) {
e[1][le[1]] = Edge(n1, board[n1], h[1][i]);
h[1][i] = le[1]++;
}
}
} int Min = INF;
for (int i = (H - 1) * W; i < n; i++) //枚举最后一行'S'进行SPFA
if (board[i] == 0)
{
spfa(i);
for (int j = 0; j < W; j++) //遍历第一行'T'的最短路长
if(board[j] == 0) Min = min(min(Min, d[0][j]), d[1][j]);
}
if (Min == INF) Min = -1;
printf("%d\n", Min);
}
return 0;
}
ACM/ICPC 之 SPFA练习两道(ZOJ3088-ZOJ3103)的更多相关文章
- ACM/ICPC 之 SPFA范例两道(POJ3268-POJ3259)
两道以SPFA算法求解的最短路问题,比较水,第二题需要掌握如何判断负权值回路. POJ3268-Silver Cow Party //计算正逆最短路径之和的最大值 //Time:32Ms Memory ...
- ACM/ICPC 之 Floyd范例两道(POJ2570-POJ2263)
两道以Floyd算法为解法的范例,第二题如果数据量较大,须采用其他解法 POJ2570-Fiber Network //经典的传递闭包问题,由于只有26个公司可以采用二进制存储 //Time:141M ...
- ACM/ICPC 之 差分约束系统两道(ZOJ2770-POJ1201)
当对问题建立数学模型后,发现其是一个差分方程组,那么问题可以转换为最短路问题,一下分别选用Bellmanford-SPFA解题 ZOJ2770-Burn the Linked Camp //差分约束方 ...
- 『ACM C++』Virtual Judge | 两道基础题 - The Architect Omar && Malek and Summer Semester
这几天一直在宿舍跑PY模型,学校的ACM寒假集训我也没去成,来学校的时候已经18号了,突然加进去也就上一天然后排位赛了,没学什么就去打怕是要被虐成渣,今天开学前一天,看到最后有一场大的排位赛,就上去试 ...
- ACM/ICPC 之 欧拉回路两道(POJ1300-POJ1386)
两道有关欧拉回路的例题 POJ1300-Door Man //判定是否存在从某点到0点的欧拉回路 //Time:0Ms Memory:116K #include<iostream> #in ...
- ACM/ICPC 之 两道dijkstra练习题(ZOJ1053(POJ1122)-ZOJ1053)
两道较为典型的单源最短路径问题,采用dijkstra解法 本来是四道练习题,后来发现后面两道用dijkstra来解的话总觉得有点冗余了,因此暂且分成三篇博客(本篇以及后两篇). ZOJ1053(POJ ...
- 2017 ACM/ICPC Asia Regional Shenyang Online spfa+最长路
transaction transaction transaction Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 132768/1 ...
- 2017 ACM/ICPC Shenyang Online SPFA+无向图最长路
transaction transaction transaction Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 132768/1 ...
- ACM - ICPC World Finals 2013 C Surely You Congest
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 试题来源 ACM/ICPC World Fin ...
随机推荐
- GCD 常用代码
GCD 常用代码 体验代码 异步执行任务 - (void)gcdDemo1 { // 1. 全局队列 dispatch_queue_t q = dispatch_get_global_queue(0, ...
- asp.net mvc中在使用async的时候HttpContext为null的问题
摘要 HttpContext上下文并不是无处不在的.详情可以看下Fish Li的文章,解释的比较清楚. HttpContext.Current并非无处不在 问题复现 public async Task ...
- 一个Struts2的实例
对Web应用程序而言,需要跨越HTTP协议的两个障碍——无状态和基于文本. 在没有使用struts的时候,你会有一个很真切的体会,就是如何把html页面上的数据提交给后台处理,以什么格式提交? 这是个 ...
- ASP.NET 5与MVC 6中的新特性
差点忘了提一句,MVC 6中默认的渲染引擎Razor也将得到更新,以支持C# 6中的新语法.而Razor中的新特性还不只这一点. 在某些情况下,直接在Web页面中嵌入某些JSON数据的方式可能比向服务 ...
- R入门<二>-时间序列研究
续之前那篇随笔 前天写完随笔后,很自豪的拿出来去跟带我入数据挖掘和SAS基础的大牛@八公炫耀,然后收获了一堆时间序列的材料,非常感谢大牛! ARIMA就是看图形,ACF和PACF,原理不需要知道,因为 ...
- <s:url>指向的Action只执行一次,清除浏览器缓存文件后又可执行一次。
Action中的方法仅为静态变量赋值,而其他访问数据库的Action可以被重复执行. 起初判断可能是静态变量的内存机制导致不能重复执行. 然后发现清楚浏览器缓存文件后又可以执行一次了,看来原因在Jsp ...
- vc++6.0各种报错合集(附:VC++6.0调出打印窗口的方法)
背景: 由于VC++6.0对于现在的我来说,只是一个工具,暂时没有太多的时间分配到这块去深究它,由于不明其原理,因此也只是在此把错误积累下来,以备下次相同错误出现时能快速排除,节省时间. 正文 一.出 ...
- wordpress如何批量关闭旧日志留言功能
于一些wordpress技术博客或者其他wordpress博客来说,一些旧日志的内容可能已经过时了,但是一些读者,还是对一些问题“纠缠不清”或者“喋喋不休”,怎么办,把留言关了就好了: UPDATE ...
- jquery选择器(三)-过滤选择器
一.基本过滤选择器 二.内容过滤选择器 1. 包含文本内容为“text”的元素 2. 含有某个选择器所匹配的父元素 3. 包含有子元素或者文本的父元素 4. 不含有子元素或者文本的父元素 三.可见性过 ...
- Ubuntu 14 Chrome字体设置备份
Ubuntu 14 Chrome字体设置备份 1.设置 -> 显示高级设置 -> 自定义字体 -> (1) 标准字体:YaHei Consolas Hybrid,14 (2) Ser ...