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

方法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. 浏览器缓存机制(HTTP缓存机制)

    其机制是根据HTTP报文的缓存标识进行的. 过程:浏览器发起HTTP请求 – 服务器响应该请求.那么浏览器第一次向服务器发起该请求后拿到请求结果,会根据响应报文中HTTP头的缓存标识,决定是否缓存结果 ...

  2. 大白话理解cookie

    HTTP协议是一个无状态的协议,服务器无法区分出两次请求是否发送自同一服务器. 需要通过会话控制来解决这个问题,会话控制主要有两种方式Cookie 和 Session. Cookie就是一个头,Coo ...

  3. retrofit post请求多文件,partMap用法

    1. APIService 定义注解 @Multipart @POST("cyxx/Feedback/add.do") Observable<ResponseBody> ...

  4. 用VS Code Debug Python

  5. 【udacity】机器学习-knn最近邻算法

    Evernote Export 1.基于实例的学习介绍 不同级别的学习,去除所有的数据点(xi​,yi​),然后放入一个数据库中,下次直接提取数据 但是这样的实现方法将不能进行泛化,这种方式只能简单的 ...

  6. Emoji表情处理工具类

    import java.util.regex.Matcher; import java.util.regex.Pattern; public class EmojiToString { /** * 将 ...

  7. python 从Excel中取值

    import openpyxl from openpyxl import load_workbook def open_file(file_path): workbook = load_workboo ...

  8. eas之控制kdtable滚动条

    //滚动条支持三种状态 自动 隐藏 显示 public static final int SCROLL_STATE_AUTO=0://自动根据数据判断是否显示或隐藏 public static fin ...

  9. 51nod1596 搬货物

    现在有n个货物,第i个货物的重量是 2wi .每次搬的时候要求货物重量的总和是一个2的幂.问最少要搬几次能把所有的货物搬完. 样例解释: 1,1,2作为一组. 3,3作为一组. Input 单组测试数 ...

  10. Mysql入门详解

    目录 数据库之Mysql 一 .简单了解数据库 二.Mysql的使用 三.多表查询 数据库之Mysql 本篇文章为观看某教学视频后所作个人总结 一 .简单了解数据库 1.1常见关系型数据库 mysql ...