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的战斗力Ai。输入数据 保证4<=n<=100000,1<=a,b<=n,1<=m<=200000,-1000<=Ai& lt;=1000.
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
【样例说明】
有四个岛,生物1在1号岛,生物2在2号岛,生物3、5、6在3号岛,生物4在4号岛。
HINT
NeverLand这个单词在“小飞侠彼得潘”中译为梦幻岛,在这却成为无归岛,真是汗啊.
正解:仙人掌$DP$。
和小c的独立集是一样的:http://www.cnblogs.com/wfj2048/p/6641693.html
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define N (100010) 16 #define il inline 17 #define RG register 18 #define ll long long 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 20 21 using namespace std; 22 23 struct edge{ int nt,to; }g[400010]; 24 25 int head[N],fa[N],dep[N],dfn[N],low[N],vis[N],val[N],f[2][N],ff[2][N],n,m,num,cnt; 26 27 il int gi(){ 28 RG int x=0,q=1; RG char ch=getchar(); 29 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 30 if (ch=='-') q=-1,ch=getchar(); 31 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 32 return q*x; 33 } 34 35 il void insert(RG int from,RG int to){ 36 g[++num]=(edge){head[from],to},head[from]=num; return; 37 } 38 39 il void dp(RG int x,RG int rt,RG int dep,RG int tot){ 40 if (dep==tot) return; RG int v; 41 for (RG int i=head[x];i;i=g[i].nt){ 42 v=g[i].to; if (fa[v]!=x || !vis[v]) continue; 43 dp(v,rt,dep+1,tot),ff[1][x]+=ff[0][v]; 44 if (v==rt) ff[0][x]+=ff[0][v]; 45 else ff[0][x]+=max(ff[0][v],ff[1][v]); 46 } 47 if (x==rt) ff[1][x]=0; return; 48 } 49 50 il void circle(RG int rt,RG int x){ 51 RG int tot=dep[x]-dep[rt]+1; 52 ff[0][rt]=f[0][rt],ff[1][rt]=f[1][rt],vis[rt]=1; 53 for (RG int i=x;i!=rt;i=fa[i]) 54 ff[0][i]=f[0][i],ff[1][i]=f[1][i],vis[i]=1; 55 dp(rt,rt,1,tot); 56 RG int res1=ff[0][rt],res2=ff[1][rt]; 57 ff[0][rt]=f[0][rt],ff[1][rt]=f[1][rt]; 58 for (RG int i=x;i!=rt;i=fa[i]) 59 ff[0][i]=f[0][i],ff[1][i]=f[1][i]; 60 dp(rt,x,1,tot); 61 f[0][rt]=max(f[0][rt],max(res1,ff[0][rt])); 62 f[1][rt]=max(f[1][rt],max(res2,ff[1][rt])); 63 for (RG int i=x;i!=rt;i=fa[i]) vis[i]=0; 64 vis[rt]=0; return; 65 } 66 67 il void dfs(RG int x,RG int p){ 68 fa[x]=p,dep[x]=dep[p]+1,f[1][x]=val[x]; 69 dfn[x]=low[x]=++cnt; RG int v; 70 for (RG int i=head[x];i;i=g[i].nt){ 71 v=g[i].to; if (v==p) continue; 72 if (!dfn[v]) dfs(v,x),low[x]=min(low[x],low[v]); 73 else low[x]=min(low[x],dfn[v]); 74 if (dfn[x]<low[v]) f[1][x]+=f[0][v],f[0][x]+=max(f[0][v],f[1][v]); 75 } 76 for (RG int i=head[x];i;i=g[i].nt){ 77 v=g[i].to; if (v==p) continue; 78 if (fa[v]!=x && dfn[x]<dfn[v]) circle(x,v); 79 } 80 return; 81 } 82 83 il void work(){ 84 n=gi(),m=gi(); 85 for (RG int i=1,x,y;i<=m;++i){ 86 x=gi(),y=gi(); 87 insert(x,y),insert(y,x); 88 } 89 for (RG int i=1;i<=n;++i) val[i]=gi(); 90 dfs(1,0); printf("%d",max(f[0][1],f[1][1])); return; 91 } 92 93 int main(){ 94 File("c"); 95 work(); 96 return 0; 97 }