BZOJ 1487 无归岛
Description
Neverland是个神奇的地方,它由一些岛屿环形排列组成,每个岛上都生活着之中与众不同的物种。但是这些物种都有一个共同的生活习性:对于同一个岛上的任意两个生物,他们有且仅有一个公共朋友,即对同一岛上的任意两个生物\(a\)和\(b\)有且仅有一个生物\(c\)既是\(a\)的朋友也是\(b\)的朋友,当然某些岛上也可能会只有一个生物孤单地生活着。这一习性有一个明显的好处,当两个生物发生矛盾的时候,他们可以请那个唯一的公共朋友来裁决谁对谁错。
另外,岛与岛之间也有交流,具体来说,每个岛都会挑选出一个最聪明的生物做代表,然后这个生物与他相邻的两个岛的代表成为朋友。
不行的是,A世界准备入侵Neverland,作为Neverland的守护者,Lostmonkey想知道在一种比较坏的情况下Never的战斗力。因为和朋友并肩作战,能力会得到提升,所以Lostmonkey想知道在不选出一对朋友的情况下Neverland的最大战斗力。即选出一些生物,且没有一对生物是朋友,并且要求它们的战斗力之和最大。
Input
第一行包含用空格隔开的两个整数\(n\)和\(m\),分别表示Neverland的生物种数和朋友对数。接下来的\(m\)行描述所有朋友对,具体来说,每行包含用空格隔开的两个整数\(a\)和\(b\),表示生物\(a\)和生物\(b\)是朋友(每对朋友只出现一次)。第\(m+2\)行包含用空格隔开的\(n\)个整数,其中第\(i\)个整数表示生物i的战斗力\(A_{i}\)。
Output
仅包含一个整数,表示满足条件的最大战斗力。
Sample Input
6 7
1 2
2 3
3 4
4 1
3 6
3 5
5 6
20 10 30 15 20 10
Sample Output
50
Hint
输入数据保证\(4 \le n \le 100000\),\(1 \le a,b \le n\),\(1 \le m \le 200000\),\(-1000 \le Ai \le 1000\)。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
#define inf (1<<30)
#define maxn 200010
int n,m,cnt,cir[maxn],w[maxn],fa[maxn],side[maxn];
int dfn[maxn],low[maxn],toit[maxn*2],next[maxn*2];
int f[maxn][2],g[maxn][2],ans;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void add(int a,int b) { next[++cnt] = side[a]; toit[cnt] = b; side[a] = cnt; }
inline void ins(int a,int b) { add(a,b); add(b,a); }
inline void dp(int root,int last)
{
int nn = 0;
while (last != root) cir[++nn] = last,last = fa[last];
cir[++nn] = root;
for (int i = 1;i <= nn;++i) g[cir[i]][0] = f[cir[i]][0],g[cir[i]][1] = f[cir[i]][1];
g[root][1] = inf;
for (int i = nn-1;i;--i)
{
g[cir[i]][0] += min(g[cir[i+1]][0],g[cir[i+1]][1]);
g[cir[i]][1] += g[cir[i+1]][0];
}
f[root][0] = min(g[cir[1]][0],g[cir[1]][1]);
for (int i = 1;i <= nn;++i) g[cir[i]][0] = f[cir[i]][0],g[cir[i]][1] = f[cir[i]][1];
g[root][0] = inf;
for (int i = nn-1;i;--i)
{
g[cir[i]][0] += min(g[cir[i+1]][0],g[cir[i+1]][1]);
g[cir[i]][1] += g[cir[i+1]][0];
}
f[root][1] = g[cir[1]][0];
}
inline void dfs(int now)
{
dfn[now] = low[now] = ++cnt;
f[now][0] = w[now];
for (int i = side[now];i;i = next[i])
if (toit[i] != fa[now])
{
if (fa[toit[i]] == now) continue;
if (!dfn[toit[i]]) fa[toit[i]] = now,dfs(toit[i]);
low[now] = min(low[now],low[toit[i]]);
if (low[toit[i]] > dfn[now])
{
f[now][0] += min(f[toit[i]][0],f[toit[i]][1]);
f[now][1] += f[toit[i]][0];
}
}
for (int i = side[now];i;i = next[i])
if (toit[i] != fa[now] && dfn[toit[i]] > dfn[now] && fa[toit[i]] != now)
dp(now,toit[i]);
}
int main()
{
freopen("1487.in","r",stdin);
freopen("1487.out","w",stdout);
n = read(); m = read();
for (int i = 1;i <= m;++i) ins(read(),read());
for (int i = 1;i <= n;++i) w[i] =read(),ans += w[i];
for (int i = 1;i <= n;++i)
if (!dfn[i]) cnt = 0,dfs(i),ans -= min(f[i][0],f[i][1]);
printf("%d",ans);
fclose(stdin); fclose(stdout);
return 0;
}
最新文章
- GUI 和 GUILayout 的区别
- LeetCode Graph Valid Tree
- 修改host
- 328. Odd Even Linked List
- sort() 方法用于对数组的元素进行排序
- bzoj1565
- poj1655(树形dp)
- 【C语言探索之旅】 第二部分第二课:进击的指针,C语言的王牌!
- 关于ios原声嵌入web页面的问题
- Scalatra--Introduction And Quick start
- MySQL5.6.36 linux rpm包安装配置文档
- 从零学习Fluter(三):Flutter的路由跳转以及state的生命周期
- PTA8
- 黄聪:C#使用GeckoFx拦截监控Http数据
- 最长增长子序列(LIS)
- C#重点内容之:接口(interface)(一)网络初级示例
- codeforces水题100道 第十一题 Codeforces Round #143 (Div. 2) A. Team (brute force)
- 【转】ORACLE Dataguard安装
- Impala查询详解
- 转发一篇能看懂的关于ingress的说明
热门文章
- 【Android - MD】之TextInputLayout的使用
- jersey 过滤器
- Linux 搭建SVN server
- BZOJ 1806 IOI2007 Miners 矿工配餐 动态规划
- C# 保存窗口为图片(保存纵断面图)
- [Flux] 2. Overview and Dispatchers
- [Flux] 1. Development Environment Setup
- java继承分析
- 聊一聊Android 6.0的运行时权限
- windows10UWP:如何判断一个文件或者文件夹是否存在?