题目传送门:https://www.luogu.com.cn/problem/P1073
思路:首先,我们目的是想要在图上dp求最优的路线,但是原图上会存在环,那么我们就要先通过tarjan缩点,将所有环缩成一个点,同时,记录每个点的最大值和最小值,缩点得到DAG后,我们可以在DAG上进行dp,每次转移有三种方式,一是保留上一个点的dp值,二是求得目前所在点的值,三是这个点本身的dp值,三者取最大就ok了。还要注意的是,在建DAG图的时候,要记录每个点的入度,在之后的dp过程中,每一个点在全部走到的时候,才能压入队列,进行更新操作,保证dp内的值是最优的,也就是无后效性。
代码:
1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 #include<vector>
5 #include<map>
6 #include<queue>
7 #include<set>
8 #include<cmath>
9 #include<list>
10 #include<cstring>
11 #include<string>
12 #include<stack>
13 #define ll long long
14 #define ull unsigned long long
15 #define inf 0x3f3f3f3f
16 #define inff 0x7fffffff
17 using namespace std;
18 const int N = 100000 + 10;
19
20 int n, m;
21 int dfn[N], low[N];
22 int dfncnt, scccnt;
23 stack<int>st;
24 bool ins[N];
25 int scc[N];
26 int w[N];
27 int in[N];
28
29 int dp[N];
30 int Max[N], Min[N];
31
32 vector<int>G[N];
33 vector<int>DAG[N];
34
35 void tarjan(int u) {
36 dfn[u] = ++dfncnt;
37 low[u] = dfncnt;
38 st.push(u);
39 ins[u] = true;
40 for (int i = 0; i < G[u].size(); i++) {
41 int v = G[u][i];
42 if (!dfn[v]) {
43 tarjan(v);
44 low[u] = min(low[u], low[v]);
45 }
46 else if (ins[v]) {
47 low[u] = min(low[u], dfn[v]);
48 }
49 }
50 if (dfn[u] == low[u]) {
51 int v;
52 ++scccnt;
53 do {
54 v = st.top();
55 st.pop();
56 ins[v] = false;
57 scc[v] = scccnt;
58 } while (u != v);
59 }
60 }
61
62 void getdag() {
63 for (int i = 1; i <= n; i++) {
64 if (!dfn[i]) {
65 tarjan(i);
66 }
67 }
68 for (int u = 1; u <= n; u++) {
69 for (int j = 0; j < G[u].size(); j++) {
70 int v = G[u][j];
71 if (scc[u] != scc[v]) {
72 DAG[scc[u]].push_back(scc[v]);
73 in[scc[v]]++;
74 }
75 }
76 }
77 }
78
79 queue<int>q;
80 void dagdp(int s) {
81
82 q.push(s);
83 dp[s] = max(dp[s], Max[s] - Min[s]);
84 while (!q.empty()) {
85
86 int u = q.front();
87 q.pop();
88 for (int i = 0; i < DAG[u].size(); i++) {
89 int v = DAG[u][i];
90 in[v]--;
91 Min[v] = min(Min[v], Min[u]);
92 dp[v] = max(dp[v], max(dp[u], Max[v] - Min[v]));
93 if (!in[v]) q.push(v);
94 }
95
96 }
97
98 }
99
100 void init() {
101 for (int i = 0; i <= N - 10; i++) G[i].clear();
102 for (int i = 0; i <= N - 10; i++) DAG[i].clear();
103 memset(dp, 0, sizeof(dp));
104 memset(scc, 0, sizeof(scc));
105 memset(ins, 0, sizeof(ins));
106 memset(dfn, 0, sizeof(dfn));
107 memset(low, 0, sizeof(low));
108 dfncnt = 0, scccnt = 0;
109 memset(Min, 0x3f, sizeof(Min));
110 }
111
112 int main() {
113
114 ios::sync_with_stdio(false);
115 cin.tie(0), cout.tie(0);
116 //int n, m;
117 cin >> n >> m;
118 init();
119 for (int i = 1; i <= n; i++) {
120 cin >> w[i];
121 }
122 for (; m; --m) {
123 int u, v, c;
124 cin >> u >> v >> c;
125 G[u].push_back(v);
126 if (c == 2) G[v].push_back(u);
127 }
128 getdag();
129 for (int i = 1; i <= n; i++) {
130 Max[scc[i]] = max(Max[scc[i]], w[i]);
131 Min[scc[i]] = min(Min[scc[i]], w[i]);
132 }
133 dagdp(scc[1]);
134 cout << dp[scc[n]] << "\n";
135
136 return 0;
137 }
前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源
我是高级初学者/中级Ruby程序员。我真的在努力提高我的Ruby技能,特别专注于编写更高效、紧凑、惯用的Ruby,遵循可靠的测试实践,学习并遵守项目结构和其他一般最佳实践。考虑到这一点,我一直在寻找好的Material来学习。我已经检查了几个PlayByPlayPeepcodescreencasts,这很棒,但不完全是我想要的。我浏览了Github,但我熟悉的大多数项目都非常庞大——我花了太多时间来解开事物实际上是如何组合在一起的,并试图建立事物的心智模型,而不是我真正花时间去理解开发过程。因此,我正在寻找紧凑、构建良好等优质项目/gems/libs的好例子。我更喜欢自包含的东西,即不
我正在一边学习TDD,一边编写一些小的ruby程序。我有以下类(class):classMyDirectorydefcheck(dir_name)unlessFile.directory?(dir_name)thenraiseRuntimeError,"#{dir_name}isnotadirectory"endendend我正在尝试用这个rspec测试来测试它。describeMyDirectorydoit"shoulderrorifdoesn'texist"doone=MyDirectory.newone.check("donee").shouldraise_exception
我正在编写一个网络应用程序(仅与Firefox兼容),它使用长轮询(通过jQuery的ajax功能)从服务器向客户端发送或多或少的持续更新。我担心长时间运行(例如,整天或整夜)的影响。基本的代码框架是这样的:functionprocessResults(xml){//dostuffwiththexmlfromtheserver}functionfetch(){setTimeout(function(){$.ajax({type:'GET',url:'foo/bar/baz',dataType:'xml',success:function(xml){processResults(xml)
我有一个使用太多内存的JavaScript应用程序。它不会使选项卡崩溃,但加载可能需要几分钟,其中大部分时间都花在了GC上。我正在使用堆分析器查看哪些函数分配的内存最多,效果很好。有没有什么方法可以让Chrome允许每个进程使用更大的JS堆,这样我就可以在减少内存压力的情况下进行测试运行,而无需等待GC几分钟?也许是我找不到的命令行参数? 最佳答案 是的,控制台中报告了jsHeapSizeLimit:>console.memoryMemoryInfo{totalJSHeapSize:42100000,usedJSHeapSize:2
我有一个页面显示了大约300页的表格数据。Firefox、Chrome、Safari都可以正常工作,但IE7、8和8的兼容性View都很糟糕。当我尝试滚动或按下向上翻页/向下翻页按钮时,它会滞后几秒钟。分页、较小的数据集和其他可用性建议不适用于此页面。假设我别无选择,只能一次显示所有这些数据……我可以做些什么来调整它?数据是通过jQuery/Ajax加载的,这似乎至少在某种程度上是可疑的,因为当我创建一个测试页面来直接呈现结果时,它并不相当那么慢,但仍然不如其他浏览器那么活泼。我过去曾成功使用SlickGrid等jQuery插件来解决类似问题,但由于需要很长时间才能解释的原因,即使使用
如果我不回来了false来自事件回调,或使用e.stopPropagationjQuery的特性,事件使DOM冒泡。在大多数情况下,我不关心事件是否冒泡。就像这个DOM结构示例一样:通常,我没有像这样的多个嵌套提交回调:$('#theDiv').submit(function(){alert('DIV!');});$('#theForm').submit(function(e){alert('FORM!'
我有一大组(>2000)时间序列数据,我想在浏览器中使用d3显示这些数据。D3非常适合向用户显示数据的一个子集(~100点),但我还想要一个“上下文”View(likethis)来显示整个数据集并允许用户选择作为子区域进行查看细节。但是,当尝试在d3中显示那么多点时,性能很糟糕。我觉得一个好的解决方案是选择一个数据样本,然后使用某种插值(样条、多项式等,这是我知道怎么做的部分)来绘制一条与实际数据。但是,我不清楚应该如何选择子集。数据(如下所示)具有相当平坦的区域,在这些区域需要较少的样本才能进行适当的插值,而其他区域的绝对导数非常高,需要更频繁的采样。更复杂的是,数据存在间隙(生成数
我刚开始使用jQuery,并且一直在寻找有关如何提高代码速度/性能的某种类型的资源。我想知道是否有人有任何提示或资源可以帮助我。谢谢,贝弗 最佳答案 我在这个主题上收藏了一些网站,希望它们能帮助您解决您需要的问题。(主题范围从简单到高级)jQueryPerformanceRules主题包括:AlwaysDescendFroman#idUseTagsBeforeClassesCachejQueryObjectsHarnessthePowerofChainingUseSub-queriesLimitDirectDOMManipulati
从JavaScript代码中删除注释会提高性能吗?我意识到这不是很好的编程实践,因为注释是开发的固有部分。我只是想知道他们是否真的在编译期间增加了一些开销。 最佳答案 无论是编译还是解释JavaScript,编译器/解释器都需要查看该行,确定它是注释,然后继续(或查看该行的某个区域)。对于Web应用程序,还需要下载注释行。所以是的,有一些开销。但是,我怀疑您能否找到这种差异很重要的真实场景。如果您正在编译您的代码,开销仅发生在编译运行期间,而不发生在后续执行期间。 关于javascrip