bzoj4316 小C的独立集

Description

图论小王子小C经常虐菜,特别是在图论方面,经常把小D虐得很惨很惨。
这不,小C让小D去求一个无向图的最大独立集,通俗地讲就是:在无向图中选出若干个点,这些点互相没有边连接,并使取出的点尽量多。
小D虽然图论很弱,但是也知道无向图最大独立集是npc,但是小C很仁慈的给了一个很有特点的图: 图中任何一条边属于且仅属于一个简单环,图中没有重边和自环。小C说这样就会比较水了。
小D觉得这个题目很有趣,就交给你了,相信你一定可以解出来的。

Input

第一行,两个数n, m,表示图的点数和边数。
第二~m+1行,每行两个数x,y,表示x与y之间有一条无向边。

Output

输出这个图的最大独立集。

Sample Input

5 6
1 2
2 3
3 1
3 4
4 5
3 5

Sample Output

2

HINT

100% n <=50000, m<=60000

 

正解:仙人掌$DP$。

这题是骑士的加强版,也是没有上司的舞会的超级加强版。。也是我第一棵独立写出来的仙人掌。。

这题做法和骑士类似,我们只要把环单独抠出来,然后分别强制不选环边上的两个点,跑最大独立集,然后再合并到仙人掌上就行了。

 

 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 (50010)
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[200010];
24 
25 int head[N],fa[N],dep[N],dfn[N],low[N],vis[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]=1;
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     dfs(1,0); printf("%d",max(f[0][1],f[1][1])); return;
90 }
91 
92 int main(){
93     File("c");
94     work();
95     return 0;
96 }

 

posted @ 2017-03-29 20:50  wfj_2048  阅读(341)  评论(0编辑  收藏  举报