[Luogu 2169] 正则表达式
[Luogu 2169] 正则表达式
感谢 0xis 推题。
记忆中很久没有过一遍写过一题了…
别被题目名称蒙骗!这不是正则表达式题目!和字符(串)处理一点关系都没有!这是个图论题啊喂!
题都没急,Capella 你急啥?
由题意得,能够本地传输的机子们处于同一强连通分量,于是 Tarjan 一遍,缩点。缩的过程中,对于两个 SCC 之间的边,选短的加。
我这里用一个 map,记录边(pair<int, int>)到边权(int)的映射,然后用 map 判断是否加边就好了。
最短路,跑一个 Dijkstra 即可(珍爱生命,远离某死亡算法不解释)。
输出 1 所在的 SCC 到 n 所在的 SCC 的路径。
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <map>
#include <queue>
#include <stack>
#define nullptr NULL
const int MAXN = 200010;
int n, m;
namespace SCC
{
bool exist[MAXN], vis[MAXN];
int num, sum, DFN[MAXN], low[MAXN], SCC[MAXN], dist[MAXN];
std :: stack<int> S;
struct Node
{
int index, dist;
Node(int index, int dist): index(index), dist(dist) {}
bool operator <(const Node& rhs) const
{
return dist > rhs.dist;
}
};
struct Graph
{
struct Edge
{
int to, w;
Edge *next;
Edge(int to, int w, Edge* next): to(to), w(w), next(next) {}
~Edge(void)
{
if(next != nullptr)
delete next;
}
}*head[MAXN];
Graph(int n)
{
std :: fill(head + 1, head + n + 1, (Edge*)nullptr);
}
~Graph(void)
{
for(int i = 1; i <= n; ++i)
delete head[i];
}
void AddEdge(int u, int v, int w)
{
head[u] = new Edge(v, w, head[u]);
}
}*G, *Gnew;
void Tarjan(int u)
{
S.push(u);
exist[u] = true;
DFN[u] = low[u] = ++num;
int v;
for(Graph :: Edge *i = G -> head[u]; i != nullptr; i = i -> next)
if(!DFN[v = i -> to])
{
Tarjan(v);
low[u] = std :: min(low[u], low[v]);
}
else if(exist[v])
low[u] = std :: min(low[u], DFN[v]);
if(DFN[u] == low[u])
{
++sum;
do
{
exist[v = S.top()] = false;
S.pop();
SCC[v] = sum;
}
while(u ^ v);
}
}
void Shrink(void)
{
std :: map<std :: pair<int, int>, int> QAQ;
std :: pair<int, int> t;
Gnew = new Graph(sum);
for(int u = 1, v; u <= n; ++u)
for(Graph :: Edge *i = G -> head[u]; i != nullptr; i = i -> next)
if(!QAQ.count(t = std :: make_pair(SCC[u], SCC[v = i -> to])) || i -> w < QAQ[t])
{
Gnew -> AddEdge(SCC[u], SCC[v], i -> w);
QAQ[t] = i -> w;
}
}
void Dijkstra(int S)
{
std :: priority_queue<Node> Q;
memset(dist, 0x3f, sizeof dist);
Q.push(Node(S, dist[S] = 0));
while(!Q.empty())
{
int u = Q.top().index, v;
Q.pop();
if(!vis[u])
{
vis[u] = true;
for(Graph :: Edge *i = Gnew -> head[u]; i != nullptr; i = i -> next)
if(dist[v = i -> to] > dist[u] + i -> w)
Q.push(Node(v, dist[v] = dist[u] + i -> w));
}
}
}
void Solve(void)
{
for(int i = 1; i <= n; ++i)
if(!DFN[i])
Tarjan(i);
Shrink();
Dijkstra(SCC[1]);
printf("%d\n", dist[SCC[n]]);
}
}
int main(void)
{
scanf("%d %d", &n, &m);
SCC :: G = new SCC :: Graph(n);
for(int i = 1, u, v, w; i <= m; ++i)
{
scanf("%d %d %d", &u, &v, &w);
SCC :: G -> AddEdge(u, v, w);
}
SCC :: Solve();
return 0;
}
谢谢阅读。
[Luogu 2169] 正则表达式的更多相关文章
- 【luogu P2169 正则表达式】 题解
题目链接:https://www.luogu.org/problemnew/show/P2169 tarjan缩点 + SPFA 缩完点之后加边注意别写错. 也可以不用建两个图,可以在一张图上判断是否 ...
- JS正则表达式常用总结
正则表达式的创建 JS正则表达式的创建有两种方式: new RegExp() 和 直接字面量. //使用RegExp对象创建 var regObj = new RegExp("(^\\s+) ...
- Python高手之路【五】python基础之正则表达式
下图列出了Python支持的正则表达式元字符和语法: 字符点:匹配任意一个字符 import re st = 'python' result = re.findall('p.t',st) print( ...
- C# 正则表达式大全
文章导读 正则表达式的本质是使用一系列特殊字符模式,来表示某一类字符串.正则表达式无疑是处理文本最有力的工具,而.NET提供的Regex类实现了验证正则表达式的方法.Regex 类表示不可变(只读)的 ...
- C#基础篇 - 正则表达式入门
1.基本概念 正则表达式(Regular Expression)就是用事先定义好的一些特定字符(元字符)或普通字符.及这些字符的组合,组成一个“规则字符串”,这个“规则字符串”用来判断我们给定的字符串 ...
- JavaScript正则表达式,你真的知道?
一.前言 粗浅的编写正则表达式,是造成性能瓶颈的主要原因.如下: var reg1 = /(A+A+)+B/; var reg2 = /AA+B/; 上述两个正则表达式,匹配效果是一样的,但是,效率就 ...
- Python 正则表达式入门(中级篇)
Python 正则表达式入门(中级篇) 初级篇链接:http://www.cnblogs.com/chuxiuhong/p/5885073.html 上一篇我们说在这一篇里,我们会介绍子表达式,向前向 ...
- 【JS基础】正则表达式
正则表达式的() [] {}有不同的意思. () 是为了提取匹配的字符串.表达式中有几个()就有几个相应的匹配字符串. (\s*)表示连续空格的字符串. []是定义匹配的字符范围.比如 [a-zA-Z ...
- JavaScript 正则表达式语法
定义 JavaScript定义正则表达式有两种方法. 1.RegExp构造函数 var pattern = new RegExp("[bc]at","i"); ...
随机推荐
- Team饭来了团队作业3需求改进与系统设计
团队名称:饭来了 人员组成: 队长:侯晓东 学号:2016012087 队员:崔啸寒 学号:2016012006 队员:方柱权 学号:201601 ...
- Week4-作业1
第四章 这一章主要讲了代码规范.复审和团队合作这两项内容. 在关于代码设计规范方面,书中讲到了关于goto的使用: “函数最好有单一的出口,为了达到这一目的, ...
- 复利计算测试(C语言)
对我们和复利计算程序,写单元测试. 有哪些场景? 期待的返回值 写测试程序. 运行测试. 测试模块 测试输入 预期结果 运行结果 bug跟踪 计算终值 (本金,年限,利率) 终值 1 (100 ...
- [转帖]七牛云对HTTPS 的解释
感觉对RTT 还有 建立连接的说明挺好的 转帖一下 学习 https://www.cnblogs.com/qiniu/p/6856012.html 序•魔戒再现 几天前,OpenSSL ...
- C++中的栈内存和堆内存的区别
数据结构中的堆与栈: 栈:是一种连续储存的数据结构,具有先进后出的性质.通常的操作有入栈(圧栈).出栈和栈顶元素.想要读取栈中的某个元素,就要将其之前的所有元素出栈才能完成.类比现实中的箱子一样. 堆 ...
- QVariant相当于一个包含大多数Qt数据类型的联合体(源码解读)
将数据存储为一个Private结构体类型的成员变量d: <qvariant.cpp> 1 QVariant::QVariant(Type type) 2 { create(type, 0) ...
- 微信 小程序布局 scroll-view
//滚动触底事件 <scroll-view scroll-y lower-threshold="0" bindscrolltolower="scrollBott ...
- HDU4791_Alice's Print Service
全场最水题. 保留打印a[i]份分别需要的钱,从后往前扫一遍,保证取得最优解. 查找的时候,二分同时判断最小值即可. 注意初值的设定应该设定为long long 的无穷大. #include < ...
- BZOJ5305 HAOI2018苹果树(概率期望+动态规划)
每种父亲编号小于儿子编号的有标号二叉树的出现概率是相同的,问题相当于求所有n个点的此种树的所有结点两两距离之和. 设f[n]为答案,g[n]为所有此种树所有结点的深度之和,h[n]为此种树的个数. 枚 ...
- [UVA 10635] Prince ans Princess
图片加载可能有点慢,请跳过题面先看题解,谢谢 这道题... 还是要点思维的... 第一眼看是个最长公共子序列,但是, \(N\le 62500\) ,并不能 \(O(n^2)\) 求 $ $ 这道题有 ...