BZOJ 4316 小C的独立集

    xiaoxiao2021-04-11  34

    仙人掌DP

    记f[i][0/1]表示i取不取,子仙人掌的最大答案。树边直接转移,环边扫一圈转移。

    感觉自己很智障,DP方程没什么问题,倒是tarjan写挂了???直接把栈里剩下的东西拿来当环上的东西也是没救了,才发现原来会有一些还没用的环留在栈里……

    #include<cstdio> #include<algorithm> #define N 500005 #define cmin(u,v) ((u)>(v)?(u)=(v):0) using namespace std; namespace runzhe2000 { const int INF = 1<<29; int n, m, ecnt = 1, last[N], dfn[N], low[N], timer, sta[N], stacnt, f[N][2], fa[N]; struct edge{int next, to;}e[N<<1]; void addedge(int a, int b) { e[++ecnt] = (edge){last[a], b}; last[a] = ecnt; } void tarjan(int x, int fae) { dfn[x] = low[x] = ++timer; for(int i = last[x]; i; i = e[i].next) { if((i^1) == fae) continue; int y = e[i].to; if(!dfn[y]) { fa[y] = x; tarjan(y, i); cmin(low[x], low[y]); if(low[y] > dfn[x]) // tree { f[x][1] += f[y][0]; f[x][0] += max(f[y][1], f[y][0]); } } else if(low[y] == dfn[x]) // ring { stacnt = 0; for(int i = y; i != x; i = fa[i]) sta[++stacnt] = i; int g[2]; g[0] = g[1] = 0; for(int i = 1; i <= stacnt; i++) { int g0 = g[0], g1 = g[1]; g[1] = g0 + f[sta[i]][1]; g[0] = max(g0, g1) + f[sta[i]][0]; } f[x][0] += max(g[0], g[1]); g[0] = -INF; g[1] = 0; for(int i = 1; i <= stacnt; i++) { int g0 = g[0], g1 = g[1]; g[1] = g0 + f[sta[i]][1]; g[0] = max(g0, g1) + f[sta[i]][0]; } f[x][1] += g[0]; } else cmin(low[x], dfn[y]); } f[x][1]++; } void main() { scanf("%d%d",&n,&m); for(int i = 1, a, b; i <= m; i++) { scanf("%d%d",&a,&b); addedge(a, b); addedge(b, a); } tarjan(1,0); printf("%d\n",max(f[1][1], f[1][0])); } } int main() { runzhe2000::main(); }
    转载请注明原文地址: https://ju.6miu.com/read-666478.html

    最新回复(0)