bzoj1487
来源:互联网 发布:计算机一级软件 编辑:程序博客网 时间:2024/05/20 20:22
这种题就是考个tarjan算法,然后题意很迷,估计岛的形状是一个大岛然后各个小岛的形成的环大小不超过3,当然大岛的大小也可能是3,所以这是此题容易错的地方
#include<iostream>#include<algorithm>#include<cstdio>using namespace std;struct edgee{int to;};edgee edge[400020];int first[100020], nextt[400020];int edgetot = 1;int n, m;int v[100020];int dp[2][100020];int parent[100020];int direct[100020];bool isinstack[100020];bool visit[100020];int dfn[100020], low[100020];int real[2][100020];int tot = 0, top = -1;void addedge(int from, int to){edge[edgetot].to = to;nextt[edgetot] = first[from];first[from] = edgetot++;edge[edgetot].to = from;nextt[edgetot] = first[to];first[to] = edgetot++;}void tarjan(int num, int fa){visit[num] = 1;parent[num] = fa;dfn[num] = low[num] = tot++;isinstack[num] = 1;for (int i = first[num]; i != -1; i = nextt[i]){int to = edge[i].to;if (!visit[to]){tarjan(to, num);low[num] = min(low[num], low[to]);if (dfn[num] <= low[to])//发现割点开始dp{int temp = direct[num];while (temp != num){real[0][temp] = dp[0][temp];real[1][temp] = dp[1][temp];temp = parent[temp];} temp = direct[num];int temp2, temp3;temp3 = dp[1][temp];dp[1][temp] = -1000000000;while (parent[temp] != num){temp2 = parent[temp];dp[1][temp2] = max(dp[1][temp2], real[1][temp2] + dp[0][temp]);dp[0][temp2] = max(dp[0][temp2], real[0][temp2] + max(dp[0][temp], dp[1][temp]));temp = temp2;}temp2 = parent[temp];dp[1][temp2] += max(0, dp[0][temp]);temp = direct[num];while (temp != num){dp[0][temp] = real[0][temp];dp[1][temp] = real[1][temp];temp = parent[temp];}temp = direct[num];while (parent[temp] != num){temp2 = parent[temp];dp[1][temp2] = max(dp[1][temp2], real[1][temp2] + dp[0][temp]);dp[0][temp2] = max(dp[0][temp2], real[0][temp2] + max(dp[1][temp], dp[0][temp]));temp = temp2;}temp2 = parent[temp];dp[0][temp2] += max(0, max(dp[0][temp], dp[1][temp]));temp = direct[num];while (temp != num){isinstack[temp] = 0;temp = parent[temp];}}}else{if (isinstack[to]&&to!=fa)//很明显对于此图to是割点{low[num] = min(low[num], dfn[to]);direct[to] = num;}}}}int main(){scanf("%d%d", &n, &m);for (int i = 1; i <= n; i++)first[i] = -1;for (int i = 0; i<m; i++){int a, b;scanf("%d%d", &a, &b);addedge(a, b);}for (int i = 1; i <= n; i++){scanf("%d", &v[i]);dp[1][i] = v[i];}tarjan(1, 1);printf("%d\n", max(dp[0][1], dp[1][1]));return 0;}
阅读全文
0 0
- bzoj1487
- bzoj1487: [HNOI2009]无归岛
- bzoj1487 无归岛
- bzoj1487 无归岛 树形dp
- Anaconda虚拟环境迁移小记录
- HDOJ--2899Strange fuction!!!!二分法 (三分)
- 数组元素的赋值的简单说明,while循环和for循环的简单说明
- u3d_rpg游戏开发之物品管理(二)
- 调用函数求任意两个整数的最小公倍数和最大公约数
- bzoj1487
- 设计模式--简单工厂-工厂方法
- java实现扫雷+AI自动扫雷策略及实现
- CSS2 总结
- 【Maven】maven配置默认使用的JDK版本及maven镜像
- STM32的复用时钟的开启和重映射功能
- linux ——apache
- uva1636(离散概率)
- 刷题笔记:C/C++专项练习4