题目大意:求图的严格次短路。

方法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 严格次短路的更多相关文章

  1. POJ3255 Roadblocks 【次短路】

    Roadblocks Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7760   Accepted: 2848 Descri ...

  2. POJ3255 Roadblocks [Dijkstra,次短路]

    题目传送门 Roadblocks Description Bessie has moved to a small farm and sometimes enjoys returning to visi ...

  3. poj3255 Roadblocks 次短路

    Roadblocks Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10098   Accepted: 3620 Descr ...

  4. 【POJ3255/洛谷2865】[Usaco2006 Nov]路障Roadblocks(次短路)

    题目: POJ3255 洛谷2865 分析: 这道题第一眼看上去有点懵-- 不过既然要求次短路,那估计跟最短路有点关系,所以就拿着优先队列优化的Dijkstra乱搞,搞着搞着就通了. 开两个数组:\( ...

  5. 【POJ - 3255】Roadblocks(次短路 Dijkstra算法)

    Roadblocks 直接翻译了 Descriptions Bessie搬到了一个新的农场,有时候他会回去看他的老朋友.但是他不想很快的回去,他喜欢欣赏沿途的风景,所以他会选择次短路,因为她知道一定有 ...

  6. poj3255 Roadblocks

    Roadblocks Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13594   Accepted: 4783 Descr ...

  7. POJ 3255 Roadblocks (次短路模板)

    Roadblocks http://poj.org/problem?id=3255 Time Limit: 2000MS   Memory Limit: 65536K       Descriptio ...

  8. 【POJ】3255 Roadblocks(次短路+spfa)

    http://poj.org/problem?id=3255 同匈牙利游戏. 但是我发现了一个致命bug. 就是在匈牙利那篇,应该dis2单独if,而不是else if,因为dis2和dis1相对独立 ...

  9. 【洛谷 P2865】 [USACO06NOV]路障Roadblocks(最短路)

    题目链接 次短路模板题. 对每个点记录最短路和严格次短路,然后就是维护次值的方法了. 和这题一样. #include <cstdio> #include <queue> #in ...

随机推荐

  1. window.dialogArguments

    弹出子窗口window.showModalDialog( url, window ); 然后在弹出的子窗口中: window.dialogArguments 即为父窗口window对象的引用.想搞什么 ...

  2. elasticsearch5.3.0 bulk index 性能调优实践

    elasticsearch5.3.0 bulk index 性能调优实践 通俗易懂

  3. AS3.0+PHP写入mySQL

    php中$_POST变量是一个数组,用于收集来自method="post"的值,内容是有HTTP POST方法发送的变量名称和值. 从带有POST方法的表单发送的信息,对任何人都是 ...

  4. windows 实时性

    在硬件编程时,大部分非智能硬件并没有主动通知反馈功能,需要PC主动轮询状态寄存器去查询硬件状态.对于运动类控制器,查询的时机(间隔)在一定程度上影响着准确率与系统负载.即使不考虑系统负载,在1000H ...

  5. HDU_1398_母函数

    Square Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  6. Luogu P1365 WJMZBMR打osu! / Easy

    概率期望专题首杀-- 毒瘤dp 首先根据数据范围推断出复杂度在O(n)左右 但不管怎么想都是n^2-- 晚上躺在床上吃东西的时候(误)想到之前有几道dp题是通过前缀和优化的 而期望的可加性又似乎为此创 ...

  7. 使用Java生成具有安全哈希的QR码

    这是关于如何在Java中使用salt生成QR代码和安全散列字符串的分步教程. 首先,需要一个可以处理QR码的库,我决定使用Zebra Crossing("ZXing")库,因为它简 ...

  8. PS通道的界面颜色设置

    编辑--首选项---界面--界面---选项---(勾选)以彩色显示通道(彩色显示)或者不勾选(为黑白色显示)

  9. 修复Thinkphp框架5.0和5.1版本的远程代码执行安全漏洞

    由于框架对控制器名没有进行足够的检测会导致在没有开启强制路由的情况下可能的getshell漏洞.最直接的影响为index.php直接被篡改成首页html的内容! 5.0版本 thinkphp/libr ...

  10. PAT_A1148#Werewolf - Simple Version

    Source: PAT 1148 Werewolf - Simple Version (20 分) Description: Werewolf(狼人杀) is a game in which the ...