• [BZOJ4316]小C的独立集(圆方树DP)


    题意:求仙人掌图直径。

    算法:建出仙人掌圆方树,对于圆点直接做普通的树上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
    ",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
    ",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
    ",f[i][0],f[i][1]); puts("");
    69     printf("%d
    ",max(f[1][0],f[1][1]));
    70     return 0;
    71 }
  • 相关阅读:
    google的开源项目总结
    Google Breakpad 完全解析(二) —— Windows前台实现篇
    Google Breakpad 完全解析(一) —— Windows入门篇
    PVS-Studio静态通用分析规则
    C,C++开源项目中的100个Bugs
    一日一点RakNet(3)--介绍
    C++开源跨平台类库集
    如何实现数组的随机排序?
    JavaScript原型,原型链 ? 有什么特点?
    js的基本数据类型
  • 原文地址:https://www.cnblogs.com/HocRiser/p/9146303.html
Copyright © 2020-2023  润新知