1. 程式人生 > >[BZOJ4316]小C的獨立集(圓方樹DP)

[BZOJ4316]小C的獨立集(圓方樹DP)

很好 stk col space amp 好的 -s sin return

題意:求仙人掌圖直徑。

算法:建出仙人掌圓方樹,對於圓點直接做普通的樹上DP(忽略方點兒子),方點做環上DP並將值直接賦給父親。

建圖時有一個很好的性質,就是一個方點在鄰接表裏的點的順序正好就是從環的根開始的整個環的點的順序,所以可以直接DP。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=l; i<=r; i++)
 4 using namespace std;
 5 
 6 const int N=100010,inf=1000000000;
 7 int n,m,tot,tim,top,u,v;
8 int dfn[N],low[N],stk[N],f[N][2],S[N][2]; 9 10 struct E{ 11 int cnt,h[N],nxt[N<<1],to[N<<1]; 12 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; } 13 }G,G1; 14 15 void Tarjan(int x,int pre){ 16 dfn[x]=low[x]=++tim; stk[++top]=x; 17 for (int i=G.h[x],k; i; i=G.nxt[i])
18 if ((k=G.to[i])!=pre){ 19 if (!dfn[k]){ 20 Tarjan(k,x); low[x]=min(low[x],low[k]); 21 if (low[k]>dfn[x]) top--,G1.add(x,k); 22 else if (low[k]==dfn[x]){ 23 tot++; int t; 24 do{ t=stk[top--]; G1.add(tot,t); } while
(t!=k); 25 G1.add(x,tot); G1.add(tot,x); 26 } 27 } 28 else low[x]=min(low[x],dfn[k]); 29 } 30 } 31 32 void dfs(int x,int fa){ printf("%d\n",x); for (int i=G1.h[x],k; i; i=G1.nxt[i]) if (G1.to[i]!=fa) dfs(G1.to[i],x); } 33 34 void DP(int x,int fa){ 35 //printf("%d\n",x); 36 if (x<=n){ 37 f[x][0]=0; f[x][1]=1; 38 for (int i=G1.h[x],k; i; i=G1.nxt[i]){ 39 DP(k=G1.to[i],x); 40 if (k<=n) f[x][0]+=max(f[k][0],f[k][1]),f[x][1]+=f[k][0]; 41 } 42 }else{ 43 for (int i=G1.h[x]; i; i=G1.nxt[i]) if (G1.to[i]!=fa) DP(G1.to[i],x); 44 45 int top=0; 46 for (int i=G1.h[x],k; i; i=G1.nxt[i]) 47 S[++top][0]=f[k=G1.to[i]][0],S[top][1]=f[k][1]; 48 for (int i=top-1; i; i--) 49 S[i][0]+=max(S[i+1][1],S[i+1][0]),S[i][1]+=S[i+1][0]; 50 f[fa][0]=S[1][0]; 51 52 top=0; 53 for (int i=G1.h[x],k; i; i=G1.nxt[i]) 54 S[++top][0]=f[k=G1.to[i]][0],S[top][1]=f[k][1]; 55 S[top][1]=-inf; 56 for (int i=top-1; i; i--) 57 S[i][0]+=max(S[i+1][1],S[i+1][0]),S[i][1]+=S[i+1][0]; 58 f[fa][1]=S[1][1]; 59 } 60 } 61 62 int main(){ 63 freopen("bzoj4316.in","r",stdin); 64 freopen("bzoj4316.out","w",stdout); 65 scanf("%d%d",&n,&m); tot=n; 66 rep(i,1,m) scanf("%d%d",&u,&v),G.add(u,v),G.add(v,u); 67 Tarjan(1,0); DP(1,0); //dfs(1,0); 68 //rep(i,1,tot) printf("%d %d\n",f[i][0],f[i][1]); puts(""); 69 printf("%d\n",max(f[1][0],f[1][1])); 70 return 0; 71 }

[BZOJ4316]小C的獨立集(圓方樹DP)