zoukankan      html  css  js  c++  java
  • Bzoj_4316 小C的独立集

    题意

    给定一个仙人掌,求出这个仙人掌的最大独立点集。

    (n leqslant 5e4,m leqslant 6e4)

    题解

    哈哈,第一次写仙人掌DP,大脑爆炸。
    这里用一种直接DP的方式。设(f_{x,i,j})表示点x的选择情况为i,点x到父亲的那条边所在的环中,深度最大(位于底部)的点的选择情况为j的最大方案。转移嘛,自己想想吧。详见代码。

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=5e4;
    int n,m,tot,ans;
    int pre[maxn*4+8],now[maxn+8],son[maxn*4+8];
    int fa[maxn+8],color[maxn+8],f[maxn+8][2][2],dep[maxn+8];
    
    int read()
    {
    	int x=0,f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    	return x*f;
    }
    
    void add(int u,int v)
    {
    	pre[++tot]=now[u];
    	now[u]=tot;
    	son[tot]=v;
    }
    
    void dfs(int x)
    {
    	dep[x]=dep[fa[x]]+1;
    	for (int p=now[x];p;p=pre[p])
    		{
    			int child=son[p];
    			if (child==fa[x]) continue;
    			if (!dep[child])
    				{
    					fa[child]=x,dfs(child);
    					for (int i=0;i<2;i++)
    							for (int j=0;j<2;j++)
    								{
    									int res=0;
    									for (int k=0;k<2;k++)
    										for (int l=0;l<2;l++)
    											{
    												if (i&k) continue;
    												if (color[child]!=2&&j!=l) continue;
    												if (color[child]==1&&k!=l) continue;
    												if (color[child]==2&&(i&l)) continue;
    												res=max(res,f[child][k][l]);
    											}
    									f[x][i][j]+=res;
    								}
    				}	
    			else
    				if (dep[x]>dep[child])
    					{
    						color[x]=1;
    						int res=x;
    						while(fa[res]!=child) res=fa[res];
    						color[res]=2;
    					}
    		}
    	f[x][1][0]++,f[x][1][1]++;
    	if (color[x]==1)
    		{
    			f[x][0][1]=f[x][0][0]=max(f[x][0][1],f[x][0][0]);
    			f[x][1][1]=f[x][1][0]=max(f[x][1][0],f[x][1][1]);
    			f[x][1][0]=f[x][0][1]=0;
    		}
    }
    
    int main()
    {
    	n=read(),m=read();
    	for (int i=1;i<=m;i++)
    		{
    			int u=read(),v=read();
    			add(u,v),add(v,u);
    		}
    	for (int i=1;i<=n;i++)
    		if (!dep[i])
    			{
    				dfs(i);
    				int res=0;
    				for (int j=0;j<2;j++)
    					for (int k=0;k<2;k++)
    						res=max(res,f[i][j][k]);
    				ans+=res;
    			}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    入侵特斯拉——智能汽车安全性分析
    D-Link系列路由器漏洞挖掘入门
    工控安全入门之 Ethernet/IP
    浅谈JS数据类型存储问题
    【备忘】12306购票必杀技
    制作炫酷的专题页面
    杂记(下)
    杂记(上)
    跨域请求解决方案
    好用的表单验证插件
  • 原文地址:https://www.cnblogs.com/Alseo_Roplyer/p/10274363.html
Copyright © 2011-2022 走看看