luogu2149 [SDOI2009] Dlaxia的路线
题目大意
在一个无向图中,定义两个点s,t的最短路径子图为一个极大边集,对于该边集内的所有有向边e,总存在一条起点为s,终点为t且经过边e的路径,使得该路径长度为s到t的最短路径长度。现给出一个无向图,s1, s2, t1, t2四个节点,求一条最长的路径,使得它满足下列条件之一:1. 该路径上的所有边都属于s1到t1的最短路径子图且属于s2到t2的最短路径子图;2. 该路径上的所有边都属于s1到t1的最短路径子图且属于t2到s2的最短路径子图。输出该路径的长度。
题解
我们可以用4次Dijkstra得到s1,t1和s2,t2的最短路径子图$G_1,G_2$,另外由$G_2$可以得到其反向图$G'_2$。然后分别在子图$G_1\cap G_2$和$G_1\cap G'_2$上进行拓扑排序求最长路径即可。本题最重要的就是从题面到数学语言的翻译过程了,如果这一点不明确,我们可能就会建立一个子图$G_1\cap(G_2\cup G'_2)$,这样就乱了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <cassert>
using namespace std; const int MAX_NODE = 1510, MAX_EDGE = 200005, INF = 0x3f3f3f3f; struct Node;
struct Edge; struct Node
{
int DistS, DistT;
bool Done;
int Dist;//Dijkstra时,它是临时的东东;TopSort时,它是真正的最长路径长度
int DfsN;
Edge *Head;
}_nodes[MAX_NODE];
int TotNode; struct HeapNode
{
Node *cur;
int Dist; HeapNode(Node *x):cur(x),Dist(x->Dist){} bool operator < (const HeapNode& a) const
{
return Dist > a.Dist;
}
}; struct Edge
{
int Weight;
bool InSPG;//在第一个人的最短路径子图中
bool InTopG;//在Top子图中
Node *To, *From;
Edge *Next, *Rev; Edge() :InTopG(false), InSPG(false){}
}_edges[MAX_EDGE];
vector<Edge*> Temp;
int _eCount; Edge *NewEdge()
{
if (_eCount < MAX_EDGE - 1)
return _edges + ++_eCount;
else
{
Temp.push_back(new Edge());
return Temp.back();
}
} Edge *AddEdge(Node *from, Node *to, int w)
{
Edge *e = NewEdge();
e->From = from;
e->To = to;
e->Weight = w;
e->Next = from->Head;
from->Head = e;
return e;
} void Build(int uId, int vId, int w)
{
Node *u = _nodes + uId, *v = _nodes + vId;
Edge *e1 = AddEdge(u, v, w), *e2 = AddEdge(v, u, w);
e1->Rev = e2;
e2->Rev = e1;
} void Dijkstra(Node *start)
{
static priority_queue<HeapNode> q;
for (int i = 1; i <= TotNode; i++)
{
_nodes[i].Dist = INF;
_nodes[i].Done = false;
}
start->Dist = 0;
q.push(start);
while (!q.empty())
{
HeapNode temp = q.top();
q.pop();
Node *cur = temp.cur;
if (cur->Done)
continue;
cur->Done = true;
for (Edge *e = cur->Head; e; e = e->Next)
{
if (cur->Dist + e->Weight < e->To->Dist)
{
e->To->Dist = cur->Dist + e->Weight;
q.push(e->To);
}
}
}
} void GetInGraph(void(*DoInGraph)(Edge*), int spLen)
{
for (int i = 1; i <= _eCount; i++)
if (_edges[i].From->DistS + _edges[i].Weight + _edges[i].To->DistT == spLen)
DoInGraph(_edges + i);
for (int i = 0; i < Temp.size(); i++)
if (Temp[i]->From->DistS + Temp[i]->Weight + Temp[i]->To->DistT == spLen)
DoInGraph(Temp[i]);
} void SetOrgGraph(Edge *e)
{
e->InSPG = true;
} void MakeTopGraph1(Edge *e)
{
if (e->InSPG)
e->InTopG = true;
} void MakeTopGraph2(Edge *e)
{
if (e->Rev->InSPG)
e->InTopG = true;
} int ShortestPath(int s, int t)
{
Node *start = _nodes + s, *target = _nodes + t;
Dijkstra(target);
for (int i = 1; i <= TotNode; i++)
_nodes[i].DistT = _nodes[i].Dist;
Dijkstra(start);
for (int i = 1; i <= TotNode; i++)
_nodes[i].DistS = _nodes[i].Dist;
return target->DistS;
} void ClearTopGraph()
{
for (int i = 1; i <= _eCount; i++)
_edges[i].InTopG = false;
for (int i = 0; i < Temp.size(); i++)
Temp[i]->InTopG = false;
} stack<Node*> St;
void Dfs(Node *cur)
{
assert(cur->DfsN != 1);
if (cur->DfsN == 2)
return;
cur->DfsN = 1;
for (Edge *e = cur->Head; e; e = e->Next)
{
if (!e->InTopG)
continue;
Dfs(e->To);
}
cur->DfsN = 2;
St.push(cur);
} int LongestPath()
{
for (int i = 1; i <= TotNode; i++)
{
_nodes[i].Dist = 0;
_nodes[i].DfsN = 0;
}
for (int i = 1; i <= TotNode; i++)
Dfs(_nodes + i);
int ans = 0;
while (!St.empty())
{
Node *cur = St.top();
St.pop();
ans = max(ans, cur->Dist);
for (Edge *e = cur->Head; e; e = e->Next)
if (e->InTopG)
e->To->Dist = max(e->To->Dist, cur->Dist + e->Weight);
}
return ans;
} int main()
{
int totEdge, s1, s2, t1, t2;
scanf("%d%d%d%d%d%d", &TotNode, &totEdge, &s1, &t1, &s2, &t2);
for (int i = 1; i <= totEdge; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
Build(u, v, w);
}
int len1 = ShortestPath(s1, t1);
GetInGraph(SetOrgGraph, len1);
int len2 = ShortestPath(s2, t2);
GetInGraph(MakeTopGraph1, len2);
int ans1 = LongestPath();
ClearTopGraph();
GetInGraph(MakeTopGraph2, len2);
int ans2 = LongestPath();
printf("%d\n", max(ans1, ans2));
return 0;
}
luogu2149 [SDOI2009] Dlaxia的路线的更多相关文章
- Luogu2149 [SDOI2009]Elaxia的路线-最短路+拓扑排序
Solution 另外$ m <=5e5$. 两条最短路的 最长公共路径 一定是若干条连续的边, 并且满足拓扑序. 于是我们分别 正向 和反向走第二条路径,若该条边同时是两条最短路径上的边, 则 ...
- BZOJ 1880: [Sdoi2009]Elaxia的路线( 最短路 + dp )
找出同时在他们最短路上的边(dijkstra + dfs), 组成新图, 新图DAG的最长路就是答案...因为两人走同一条路但是不同方向也可以, 所以要把一种一个的s,t换一下再更新一次答案 ---- ...
- 【BZOJ1880】[Sdoi2009]Elaxia的路线(最短路)
[BZOJ1880][Sdoi2009]Elaxia的路线(最短路) 题面 BZOJ 洛谷 题解 假装我们知道了任意两点间的最短路,那么我们怎么求解答案呢? 不难发现公共路径一定是一段连续的路径(如果 ...
- 洛谷 P2149 [SDOI2009]Elaxia的路线 解题报告
P2149 [SDOI2009]Elaxia的路线 题目描述 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. Elaxia ...
- 【BZOJ 1880】 [Sdoi2009]Elaxia的路线 (最短路树)
1880: [Sdoi2009]Elaxia的路线 Description 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. ...
- BZOJ1880: [Sdoi2009]Elaxia的路线(最短路)
1880: [Sdoi2009]Elaxia的路线 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 2049 Solved: 805 题目链接:https ...
- 【BZOJ1880】[SDOI2009]Elaxia的路线 (最短路+拓扑排序)
[SDOI2009]Elaxia的路线 题目描述 最近,\(Elaxia\)和\(w**\)的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. \(El ...
- 【BZOJ1880】[Sdoi2009]Elaxia的路线 最短路+DP
[BZOJ1880][Sdoi2009]Elaxia的路线 Description 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起 ...
- 洛谷——P2149 [SDOI2009]Elaxia的路线
P2149 [SDOI2009]Elaxia的路线 题目描述 最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间.Elaxia和w每 ...
随机推荐
- [Windows Server 2012] 手工破解MySQL密码
★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频.★ 本节我们将带领大家:破解MySQL ...
- vue里的tab控件
如下图,v-model绑定的值,这个值在js里一旦改变,视图就会切换到相应的tab页,这意味着一定要先给tab页内容数据赋值,再改变这个tabsIndex的值 如下图,先赋值data列表数据,在更改t ...
- 如何在mac里面,把xcode代码同步到 tfs 的 git库(克隆git篇)
如果是新的git库,还没有任何内容可以克隆,可以参考:http://www.cnblogs.com/IWings/p/6755795.html 在mac安装visual studio code htt ...
- FTP服务器访问主动模式、被动模式
在公司里面,经常需要访问外网FTP取资料等情况.但是有时用windows界面访问经常遇到各种问题. 下面介绍两种客户端是如何访问ftp服务器. 首先我们需要说明:防火墙,是阻拦外界与内部的通讯的一道关 ...
- iview Table表格单选框互斥
表格中添加单选框,并且互斥 首先带data中定义 currentid : 0 :表示默认不选中 { title: "名称", key: "name", re ...
- Mapreduce代码疑点(1)
一.Hadoop MultipleInputs.addInputPath 读取多个路径 https://blog.csdn.net/t1dmzks/article/details/76473905 M ...
- python利用7z批量解压rar
一开始我使用了rarfile这个库,奈何对于含有密码的压缩包支持不好,在linux上不抛出异常:之后有又尝试了unrar..比rarfile还费劲.. 所以用了调用系统命令的方法,用7z来解压 通过a ...
- NOIp知识点复习——最短路计数
$Mingqi\_H$ NOIp 2017考挂了...gg 重新开始好了. 计划明年2月24号前复习完所有的NOIp知识点(毕竟很不熟练啊),之后到七月底前学习完省选的东西(flag?). 从现在开始 ...
- 17.使用原生cross-fiels技术解决搜索弊端
主要知识点: 原生cross-fiels的用法 原生cross-fiels解决三个弊端 一.原生cross-fiels的用法 GET /forum/article/_search { ...
- 5.terms搜索多个值以及多值搜索结果优化
主要知识点 terms搜索多个值,并和term的比较 一.term和terms terms是在这个字段中搜索多个值,相当于sql中的in语法 (select * from tbl where ...