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