bzoj4316 小C的独立集

题目描述:

bz

题解:

仙人掌上$tarjan$。

当然$dfs$树可做但是好像都一样。

考虑用环的顶点表示这个环的贡献,可以依靠$tarjan$进行$dp$。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 50050;
const int M = 60050;
const int inf = 0x3f3f3f3f;
template<typename T>
inline void read(T&x)
{
    T f = 1,c = 0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
    x = f*c;
}
int n,m,hed[N],cnt=1;
struct EG
{
    int to,nxt;
}e[2*M];
void ae(int f,int t)
{
    e[++cnt].to = t;
    e[cnt].nxt = hed[f];
    hed[f] = cnt;
}
int dp[N][2],dep[N],low[N],tim,sta[N],tl;
int s[N][2];
int r[N],tr;
int sol(int z)
{
    s[1][0] = (z)?-inf:0,s[1][1] = (z)?0:-inf;
    for(int i=2;i<=tr;i++)
    {
        s[i][0] = dp[r[i]][0]+max(s[i-1][0],s[i-1][1]);
        s[i][1] = dp[r[i]][1]+s[i-1][0];
    }
    return (z)?s[tr][0]:max(s[tr][0],s[tr][1]);
}
void tarjan(int u,int pre)
{
    dep[u] = low[u] = ++tim;
    sta[++tl] = u;
    dp[u][0]=0,dp[u][1]=1;
    for(int j=hed[u];j;j=e[j].nxt)
    {
        int to = e[j].to;
        if(j==pre)continue;
        if(!dep[to])
        {
            tarjan(to,j^1);
            low[u] = min(low[u],low[to]);
            if(low[to]>dep[u])
            {
                dp[u][0] += max(dp[to][0],dp[to][1]);
                dp[u][1] += dp[to][0];
                tl--;
            }else if(low[to]==dep[u])
            {
                r[tr=1] = u;
                while(sta[tl+1]!=to)r[++tr]=sta[tl--];
                dp[u][0]+=sol(0);
                dp[u][1]+=sol(1);
            }
        }else    low[u] = min(low[u],dep[to]);
    }
}
int main()
{
//    freopen("1.in","r",stdin);
    read(n),read(m);
    for(int f,t,i=1;i<=m;i++)
    {
        read(f),read(t);
        ae(f,t),ae(t,f);
    }
    tarjan(1,0);
    printf("%d\n",max(dp[1][0],dp[1][1]));
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/LiGuanlin1124/p/10809430.html