POJ3255 Roadblocks 严格次短路
题目大意:求图的严格次短路。
方法1:
SPFA,同时求单源最短路径和单源次短路径。站在节点u上放松与其向量的v的次短路径时时,先尝试由u的最短路径放松,再尝试由u的次短路径放松(该两步并非非此即彼)。
由u的最短路径放松:
if(u->Dist + e->Weight < v->Dist)
v->Dist2=v->Dist;
//此处隐藏最短路放松。次短路不在此固定,Dist2可能在由u次短路放松时被放松得更短 if(u->Dist + e->Weight > v->Dist && u->Dist + e->Weight < v->Dist2)
v->Dist2=u->Dist+e->Weight;
由u的次短路经放松:
if(u->Dist2 + e->Weight > v->Dist && u->Dist2 + e->Weight < v->Dist2)
v->Dist2=u->Dist2 + e->Weight;
完整代码:
#include <cstdio>
#include <cstring>
#include <cassert>
#include <queue>
using namespace std; #define LOOP(i,n) for(int i=1; i<=n; i++)
const int MAX_NODE = , MAX_EDGE = * , INF = 0x3f3f3f3f; struct Node;
struct Edge; struct Node
{
int Id, Dist, Dist2;
bool Inq;
Edge *Head;
}_nodes[MAX_NODE], *Start, *Target;
int _vCount; struct Edge
{
int Weight;
Node *From, *To;
Edge *Next;
Edge() {}
Edge(Node *from, Node *to, Edge *next, int weight) :
From(from), To(to), Next(next), Weight(weight){}
}*_edges[MAX_EDGE];
int _eCount; void Init(int vCount)
{
memset(_nodes, , sizeof(_nodes));
_vCount = vCount;
_eCount = ;
Start = + _nodes;
Target = vCount + _nodes;
} void AddEdge(Node *from, Node *to, int weight)
{
Edge *e = _edges[++_eCount] = new Edge(from, to, from->Head, weight);
e->From->Head = e;
} void Build(int uId, int vId, int weight)
{
Node *u = uId + _nodes, *v = vId + _nodes;
u->Id = uId;
v->Id = vId;
AddEdge(u, v, weight);
AddEdge(v, u, weight);
} void SPFA()
{
LOOP(i, _vCount)
_nodes[i].Dist = _nodes[i].Dist2 = INF;
static queue<Node*> q;
Start->Dist = ;
Start->Dist2 = INF;
Start->Inq = true;
q.push(Start);
while (!q.empty())
{
Node *u = q.front();
q.pop();
u->Inq = false;
for (Edge *e = u->Head; e; e = e->Next)
{
bool relaxOk = false;
if (u->Dist + e->Weight < e->To->Dist)
{
e->To->Dist2 = e->To->Dist;
e->To->Dist = u->Dist + e->Weight;
relaxOk = true;
}
else if (u->Dist + e->Weight > e->To->Dist && u->Dist + e->Weight < e->To->Dist2)
{
e->To->Dist2 = u->Dist + e->Weight;
relaxOk = true;
}
if (u->Dist2 + e->Weight < e->To->Dist2)
{
e->To->Dist2 = u->Dist2 + e->Weight;
relaxOk = true;
}
if (relaxOk && !e->To->Inq)
{
e->To->Inq = true;
q.push(e->To);
}
}
}
} int main()
{
#ifdef _DEBUG
freopen("c:\\noi\\source\\input.txt", "r", stdin);
#endif
int testCase, totNode, totEdge, uId, vId, weight, sId, tId;
scanf("%d%d", &totNode, &totEdge);
Init(totNode);
LOOP(i, totEdge)
{
scanf("%d%d%d", &uId, &vId, &weight);
Build(uId, vId, weight);
}
SPFA();
printf("%d\n", Target->Dist2);
return ;
}
方法2:
Dijkstra。其需用到优先队列,维护一对数据:一个节点u以及它到原点的路径d。d可以是u的最短路径,也可以是u的次短路径,但我们不用管它,我们只管放松。它能放松v最短路就放松v最短路,再不行看看它能不能放松v次短路。
完整代码:
#include <cstdio>
#include <cstring>
#include <cassert>
#include <queue>
#include <vector>
#include <functional>
using namespace std; #define LOOP(i,n) for(int i=1; i<=n; i++)
const int MAX_NODE = , MAX_EDGE = * , INF = 0x3f3f3f3f; struct Node;
struct Edge; struct Node
{
int Id, Dist, Dist2;
bool Inq;
Edge *Head;
}_nodes[MAX_NODE], *Start, *Target;
int _vCount; struct Edge
{
int Weight;
Node *From, *To;
Edge *Next;
Edge() {}
Edge(Node *from, Node *to, Edge *next, int weight) :
From(from), To(to), Next(next), Weight(weight) {}
}*_edges[MAX_EDGE];
int _eCount; void Init(int vCount)
{
memset(_nodes, , sizeof(_nodes));
_vCount = vCount;
_eCount = ;
Start = + _nodes;
Target = vCount + _nodes;
} void AddEdge(Node *from, Node *to, int weight)
{
Edge *e = _edges[++_eCount] = new Edge(from, to, from->Head, weight);
e->From->Head = e;
} void Build(int uId, int vId, int weight)
{
Node *u = uId + _nodes, *v = vId + _nodes;
u->Id = uId;
v->Id = vId;
AddEdge(u, v, weight);
AddEdge(v, u, weight);
} #define Pair pair<int,Node*>
void Dijkstra()
{
static priority_queue<Pair, vector<Pair>, greater<Pair>> q;
LOOP(i, _vCount)
_nodes[i].Dist = _nodes[i].Dist2 = INF;
Start->Dist = ;
q.push(Pair(, Start));
while (!q.empty())
{
Pair cur = q.top();
q.pop();
Node *u = cur.second;
int prevDist = cur.first;
//printf("prevDist %d\n", prevDist);
assert(prevDist >= u->Dist);
for (Edge *e = u->Head; e; e = e->Next)
{
if (prevDist + e->Weight < e->To->Dist)
{
e->To->Dist2 = e->To->Dist;
e->To->Dist = prevDist + e->Weight;
q.push(Pair(e->To->Dist, e->To));
}
else if (e->To->Dist < prevDist+e->Weight
&&prevDist+e->Weight < e->To->Dist2)
{
e->To->Dist2 = prevDist + e->Weight;
q.push(Pair(e->To->Dist2, e->To));
}
}
}
} int main()
{
#ifdef _DEBUG
freopen("c:\\noi\\source\\input.txt", "r", stdin);
#endif
int testCase, totNode, totEdge, uId, vId, weight, sId, tId;
scanf("%d%d", &totNode, &totEdge);
Init(totNode);
LOOP(i, totEdge)
{
scanf("%d%d%d", &uId, &vId, &weight);
Build(uId, vId, weight);
}
Dijkstra();
printf("%d\n", Target->Dist2);
return ;
}
方法3:
我们假设一条边e在次短路径内,知道这条次短路径长度d[e]是多少。那么,我们枚举每个e,求出min{d[e]}即可。具体我们需要求出每一个节点到原点的最短路径和到汇点的最短路径。这样,d[e]=e->From->DistS + e->Weight + e->To->DistT。这样求出的d[e]可能与最短路径相等。此时怎样把它转化成次短路?只能将e重复走一遍!这样,d[e]'=e->From->DistS + e->Weight * 2 + e->From->DistT。
完整代码:
#include <cstdio>
#include <cstring>
#include <cassert>
#include <queue>
#include <vector>
#include <functional>
using namespace std; #define LOOP(i,n) for(int i=1; i<=n; i++)
const int MAX_NODE = , MAX_EDGE = * , INF = 0x3f3f3f3f; struct Node;
struct Edge; struct Node
{
int Id, Dist, Dist2;
bool Inq;
Edge *Head;
}_nodes[MAX_NODE], *Start, *Target;
int _vCount; struct Edge
{
int Weight;
Node *From, *To;
Edge *Next;
Edge() {}
Edge(Node *from, Node *to, Edge *next, int weight) :
From(from), To(to), Next(next), Weight(weight) {}
}*_edges[MAX_EDGE];
int _eCount; void Init(int vCount)
{
memset(_nodes, , sizeof(_nodes));
_vCount = vCount;
_eCount = ;
Start = + _nodes;
Target = vCount + _nodes;
} void AddEdge(Node *from, Node *to, int weight)
{
Edge *e = _edges[++_eCount] = new Edge(from, to, from->Head, weight);
e->From->Head = e;
} void Build(int uId, int vId, int weight)
{
Node *u = uId + _nodes, *v = vId + _nodes;
u->Id = uId;
v->Id = vId;
AddEdge(u, v, weight);
AddEdge(v, u, weight);
} void SPFA(Node *start)
{
LOOP(i, _vCount)
{
_nodes[i].Dist = INF;
_nodes[i].Inq = false;
}
static queue<Node*> q;
start->Dist = ;
start->Inq = true;
q.push(start);
while (!q.empty())
{
Node *u = q.front();
q.pop();
u->Inq = false;
for (Edge *e = u->Head; e; e = e->Next)
{
if (u->Dist + e->Weight < e->To->Dist)
{
e->To->Dist = u->Dist + e->Weight;
if (!e->To->Inq)
{
e->To->Inq = true;
q.push(e->To);
}
}
}
}
} int Proceed()
{
SPFA(Target);
int minDist = Start->Dist, ans = INF;
LOOP(i, _vCount)
_nodes[i].Dist2 = _nodes[i].Dist;
SPFA(Start);
LOOP(i, _eCount)
{
Edge *e = _edges[i];
int temp = e->From->Dist + e->Weight + e->To->Dist2;
if (minDist < temp&&temp < ans)
ans = temp;
else
{
temp = e->From->Dist + e->From->Dist2 + e->Weight * ;
ans = min(ans, temp);
}
}
return ans;
} int main()
{
#ifdef _DEBUG
freopen("c:\\noi\\source\\input.txt", "r", stdin);
#endif
int testCase, totNode, totEdge, uId, vId, weight, sId, tId;
scanf("%d%d", &totNode, &totEdge);
Init(totNode);
LOOP(i, totEdge)
{
scanf("%d%d%d", &uId, &vId, &weight);
Build(uId, vId, weight);
}
printf("%d\n", Proceed());
return ;
}
POJ3255 Roadblocks 严格次短路的更多相关文章
- POJ3255 Roadblocks 【次短路】
Roadblocks Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 7760 Accepted: 2848 Descri ...
- POJ3255 Roadblocks [Dijkstra,次短路]
题目传送门 Roadblocks Description Bessie has moved to a small farm and sometimes enjoys returning to visi ...
- poj3255 Roadblocks 次短路
Roadblocks Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10098 Accepted: 3620 Descr ...
- 【POJ3255/洛谷2865】[Usaco2006 Nov]路障Roadblocks(次短路)
题目: POJ3255 洛谷2865 分析: 这道题第一眼看上去有点懵-- 不过既然要求次短路,那估计跟最短路有点关系,所以就拿着优先队列优化的Dijkstra乱搞,搞着搞着就通了. 开两个数组:\( ...
- 【POJ - 3255】Roadblocks(次短路 Dijkstra算法)
Roadblocks 直接翻译了 Descriptions Bessie搬到了一个新的农场,有时候他会回去看他的老朋友.但是他不想很快的回去,他喜欢欣赏沿途的风景,所以他会选择次短路,因为她知道一定有 ...
- poj3255 Roadblocks
Roadblocks Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 13594 Accepted: 4783 Descr ...
- POJ 3255 Roadblocks (次短路模板)
Roadblocks http://poj.org/problem?id=3255 Time Limit: 2000MS Memory Limit: 65536K Descriptio ...
- 【POJ】3255 Roadblocks(次短路+spfa)
http://poj.org/problem?id=3255 同匈牙利游戏. 但是我发现了一个致命bug. 就是在匈牙利那篇,应该dis2单独if,而不是else if,因为dis2和dis1相对独立 ...
- 【洛谷 P2865】 [USACO06NOV]路障Roadblocks(最短路)
题目链接 次短路模板题. 对每个点记录最短路和严格次短路,然后就是维护次值的方法了. 和这题一样. #include <cstdio> #include <queue> #in ...
随机推荐
- HBase编程 API入门系列之get(客户端而言)(2)
心得,写在前面的话,也许,中间会要多次执行,连接超时,多试试就好了. 前面是基础,如下 HBase编程 API入门系列之put(客户端而言)(1) package zhouls.bigdata.Hba ...
- SQLServer2008 关于Having
转自百度百科 与where 相比 HAVING 子句对 GROUP BY 子句设置条件的方式与 WHERE 子句和 SELECT 语句交互的方式类似. WHERE 子句搜索条件在进行分组操作之前应用: ...
- CDN 内容分发网络
第一步,HTML的文件引用:HTML的文件头(也有文件中,文件尾)那边常有其他文件引用,比如CSS以及JS的引用. 就以bootstrap常用的引用来举个栗子你常见的引用可能会是这样的: <he ...
- poj3009 Curling 2.0 深搜
PS:以前看到题目这么长就没写下去了.今天做了半天,没做出来.准备看题解,打开了网站都忍住了,最后还是靠自己做出来的.算是一点进步吧. 分析: 题目的意思没明白或者理解有偏差都没办法做题.看样例3和样 ...
- mssql server 2005自动备份数据库
(转) (1)启动[sql server Management Studio],在[对象资源管理器]窗口里选择[管理]——[维护计划]选项. 2)右击[维护计划],在弹出的快捷菜单里选择[维护计划向导 ...
- C#中SetWindowPos函数详解
[DllImport("user32.dll")] private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWnd ...
- 图像局部显著性—点特征(SURF)
1999年的SIFT(ICCV 1999,并改进发表于IJCV 2004,本文描述):参考描述:图像特征点描述. 参考原文:SURF特征提取分析 本文有大量删除,如有疑义,请参考原文. SURF对SI ...
- 与swift协议相关的技术
一.协议定义与实现: 1.关联类型: 2.协议组合: 3.协议扩展: 4.协议实现. 二.协议使用:
- CDR服装设计-旗袍款式图
在服装行业中的服装款式设计.图案设计和面料设计等方面,CorelDRAW是一款常用绘图设计软件,用CorelDRAW绘制款式图比手绘更容易表达服装结构.比例.图案.色彩等要素,服装款图主要目的是为了更 ...
- matlab学习滚动条改变文本数值
如下分别添加滚动条,静态文本框和可编辑文本框,字体大小改为10,string值按下图,并使用对齐工具 保存名为GUI_02,会自动出来一个.m文件 注意代码一个字都不要错 %定义变量var,保存滚动条 ...