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;}

原创粉丝点击