BZOJ4316 : 小C的獨立集
阿新 • • 發佈:2017-09-14
ons include 最大獨立集 復雜 getch 時間復雜度 ans a* 底部
取一棵原圖的DFS生成樹,那麽因為是仙人掌,所以每條樹邊最多只會屬於一個環。
設$f[i][j][k]$表示考慮$i$的子樹,$i$點選擇情況為$j$,$i$到父親對應的環邊底部的點選擇情況為$k$時的最大獨立集。
然後直接樹形DP即可,在每個環的底部以及頂部的兩條邊處特殊處理轉移。
時間復雜度$O(n+m)$。
#include<cstdio> #define rep(i) for(int i=0;i<2;i++) const int N=50010,M=60010; int n,m,i,x,y,g[N],v[M<<1],nxt[M<<1],ed,ans; int vis[N],dfn,p[N],f[N][2][2],h[2][2];bool top[N],bot[N]; inline void read(int&a){char c;while(!(((c=getchar())>=‘0‘)&&(c<=‘9‘)));a=c-‘0‘;while(((c=getchar())>=‘0‘)&&(c<=‘9‘))(a*=10)+=c-‘0‘;} inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;} inline void up(int&a,int b){a<b?(a=b):0;} void dfs(int x,int y){ vis[x]=++dfn;p[x]=y; for(int i=g[x];i;i=nxt[i])if(v[i]!=y&&vis[v[i]])bot[x]=1; f[x][1][bot[x]]=1; for(int i=g[x];i;i=nxt[i]){ int u=v[i]; if(u==y)continue; if(!vis[u]){ dfs(u,x); rep(j)rep(k)h[j][k]=0; rep(j)rep(k)rep(a)rep(b){ if(j&&a)continue; if(top[u]&&j&&b)continue; up(h[j][k|(b&!top[u])],f[x][j][k]+f[u][a][b]); } rep(j)rep(k)f[x][j][k]=h[j][k]; }else if(vis[u]<vis[x]){ int o=x; while(p[o]!=u)o=p[o]; top[o]=1; } } } int main(){ read(n),read(m); while(m--)read(x),read(y),add(x,y),add(y,x); for(i=1;i<=n;i++)if(!vis[i]){ dfs(i,0); x=0; rep(j)rep(k)up(x,f[i][j][k]); ans+=x; } return printf("%d",ans),0; }
BZOJ4316 : 小C的獨立集