洛谷 P2607 [ZJOI2008]骑士

来源:互联网 发布:日本爱知流量计 编辑:程序博客网 时间:2024/05/18 03:25

题面

题意

给出一幅有n个点,n条边的无向未必联通图,每一个点有一个权并与另外一个点相连,对其中一些点进行染色,且相邻两点的颜色不能都染,则最大的染色点权值和是多少.

分析

这题和 洛谷P1453城市环路 很像,区别就在于它不是连通图.
因而可以先用并查集和vector进行分块,易证每一块都是比树多一条边的连通图,每一块再按照洛谷 P1453 城市环路的做法做即可.

代码

//#pragma GCC optimize(3)#include<iostream>#include<cstdio>#include<cstring>#include<vector>#define N 1001000#define db double#define ll long longusing namespace std;struct Bn{    ll next,to;};Bn bn[N*2];ll n,ans,an,zl[N],bb,first[N],s,t,dp[N][2],fa[N],j1,j2;bool vis[N],get;vector<int>jh[N];inline void add(ll u,ll v){    bb++;    bn[bb].next=first[u];    bn[bb].to=v;    first[u]=bb;}void find(ll now,ll last){    if(get) return;    ll p=first[now];    for(; p!=-1; p=bn[p].next)    {        if(bn[p].to==last) continue;        if(vis[bn[p].to])        {            s=now;            t=bn[p].to;            get=1;            return;        }        vis[bn[p].to]=1;        find(bn[p].to,now);    }}ll dfs(ll now,bool rs,ll last){    if(dp[now][rs]!=-1) return dp[now][rs];    ll i,j,res=0,p=first[now];    if(rs)    {        for(; p!=-1; p=bn[p].next)        {            if(bn[p].to==last||p==j1||p==j2) continue;            res+=dfs(bn[p].to,0,now);        }    }    else    {        for(; p!=-1; p=bn[p].next)        {            if(bn[p].to==last||p==j1||p==j2) continue;            res+=max(dfs(bn[p].to,0,now),dfs(bn[p].to,1,now)+zl[bn[p].to]);        }    }    dp[now][rs]=res;    return res;}int gf(int u){    if(u==fa[u]) return u;    fa[u]=gf(fa[u]);    return fa[u];}int main(){    register ll i,j,k,p,q;    memset(first,-1,sizeof(first));    memset(dp,-1,sizeof(dp));    cin>>n;    for(i=1; i<=n; i++) fa[i]=i;    for(i=1; i<=n; i++)    {        scanf("%lld%lld",&p,&q);        zl[i]=p;        add(i,q);        add(q,i);        fa[gf(i)]=gf(q);    }    for(i=1; i<=n; i++)    {        jh[gf(i)].push_back(i);    }    for(i=1; i<=n; i++)    {        if(!jh[i].size()) continue;        find(jh[i][0],-1);        p=first[s];        for(; p!=-1; p=bn[p].next)        {            if(bn[p].to==t)            {                j1=p;                break;            }        }        p=first[t];        for(; p!=-1; p=bn[p].next)        {            if(bn[p].to==s)            {                j2=p;                break;            }        }        an=dfs(s,0,-1);        for(j=0; j<jh[i].size(); j++)        {            dp[jh[i][j]][0]=dp[jh[i][j]][1]=-1;        }        ans+=max(an,dfs(t,0,-1));        get=s=t=j1=j2=0;    }    cout<<ans;    return 0;}
原创粉丝点击