codeforces 894E
来源:互联网 发布:淘宝官方活动报名入口 编辑:程序博客网 时间:2024/06/06 02:11
(强连通+dp)
题意:给定一个单向边的图
思路:由于每条路可以走很多遍,那么最好情况下是一直将每这条路重复走,直至该路上宝石被捡完。于是想到只有图中出现环可以这样,于是想到了tarjan缩点。缩点后,对于强连通内部的点来说,最关键的是想到:无论从哪一点出发,终点在哪里,在内部能捡到的宝石数目都是相同的,然后对于每个强连通计数即可;而对于强连通外部的DAG上,利用dp或者记忆化搜索的方式求解全局最优就好。
时间复杂度:缩点和计数的复杂度均为
#include <cstdio>#include <cmath>#include <algorithm>#include <cstring>#include <stack>#define LL long longusing namespace std;const int maxn = 1000050;const int inf = 0x3f3f3f3f;// basic structureint head[maxn], cnt;struct edge{ int to, next, w;}edge[maxn];void add_edge(int u, int v, int w) { edge[cnt].to = v; edge[cnt].w = w; edge[cnt].next = head[u]; head[u] = cnt ++;}// old_graphstack<int> s;int scc, dfs_clock;int DFN[maxn], low[maxn], blg[maxn]; //Depth First Number, low, belongbool instack[maxn]; //vis// new_graphLL dp[maxn], dis[maxn];int new_edge[maxn][3], new_cnt;void init_graph() { cnt = 0; memset(head, -1, sizeof(head));}void init_scc(int n) { scc = dfs_clock = 0; memset(DFN, -1, sizeof(DFN)); memset(instack, 0, sizeof(instack)); while(!s.empty()) s.pop();}void tarjan(int u) { int v = 0; DFN[u] = low[u] = dfs_clock ++; s.push(u); instack[u] = 1; for(int k=head[u]; k!=-1; k=edge[k].next) { v = edge[k].to; if(DFN[v] == -1) tarjan(v),low[u] = min(low[u],low[v]); else if(instack[v]) low[u] = min(low[u],DFN[v]); } if(low[u] == DFN[u]) { scc ++; do { v = s.top(); s.pop(); blg[v] = scc; instack[v] = 0; } while(v != u); }}void rebuild_graph(int n) { new_cnt = 0; for(int u=1; u<=n; u++) { for(int k=head[u]; k!=-1; k=edge[k].next) { int v = edge[k].to, w = edge[k].w; if(blg[u] == blg[v]) { int t = floor((-1+sqrt(1+8*w))/2); // n dp[blg[u]] += (LL)(t+1)*w - (LL)t*(t+1)*(t+2)/6; } else { new_edge[new_cnt][0] = blg[u], new_edge[new_cnt][1] = blg[v]; new_edge[new_cnt][2] = w; new_cnt ++; } } } init_graph(); for(int i=0; i<new_cnt; i++) add_edge(new_edge[i][0], new_edge[i][1], new_edge[i][2]);}LL dfs(int u) { if(dis[u] != -1) return dis[u]; LL ret = dp[u]; for(int k=head[u]; k!=-1; k=edge[k].next) { int v = edge[k].to, w = edge[k].w; ret = max(ret, dp[u] + (LL)w + dfs(v)); } dis[u] = ret; return ret;}int main() { //freopen("test.txt","r",stdin); int n, m, start; scanf("%d%d",&n,&m); init_graph(); init_scc(n); while(m --) { int u, v, w; scanf("%d%d%d",&u,&v,&w); add_edge(u, v, w); } scanf("%d",&start); for(int i=1; i<=n; i++) if(DFN[i] == -1) tarjan(i); rebuild_graph(n); for(int i=1; i<=scc; i++) dis[i] = -1; LL ans = dfs(blg[start]); printf("%I64d\n",ans); return 0;}
阅读全文
2 0
- codeforces 894E
- codeforces 894E
- codeforces 894 E(scc + dp)
- [Codeforces 894E] Ralph and Mushrooms
- codeforces 163E e-Government
- 【Codeforces 163E】E-Government
- Codeforces 78E Evacuation
- 【dp】codeforces 83E
- Codeforces 124 E
- Codeforces 231E
- Codeforces 231E - Cactus
- Codeforces #163 Div2 E
- codeForces 35E
- Codeforces 35E
- Playlist codeforces 268E
- Codeforces 148E(Porcelain)
- codeforces round#177 E
- codeforces 203E Transportation
- 【python 自然语言处理】对胡歌【猎场】电视剧评论进行情感值分析
- C#调用C++动态库
- 2012第三届蓝桥杯 C/C++本科组真题及题解(未完待续)
- 如何在jsp页面判断网页是被安卓设备访问还是IOS设备访问
- 虚拟机安装SSH服务
- codeforces 894E
- 2017/11/28 实习笔记 Mysql基础
- 纵横直方字体设计器
- java中常量变量和部分总结一
- QT 一些非常常用的操作
- 介绍“自顶向下,逐步求精”的方法
- [13]_keil_MDK获取、安装、破解
- cocos2d-lua消除游戏实战(一)主场景和游戏场景设计
- 浮点数表示方法