Luogu P2607 [ZJOI2008] Knight - Problem Solution

The main idea of ​​the title portal
:
Each knight has its own combat power and cannot go out with another specific knight at the same time. What is the maximum total combat power of the knights on the expedition (the total combat power is equal to the sum of the combat power of all the knights on the expedition)


Thinking process:
Students who have done Luogu P1352 Prom without a boss will definitely think this question and it are very interesting, but that question is a tree with n points and n-1 sides, this question is n points and n sides The base ring tree has only one more ring. We have to think about how to transform. We first find an edge on the ring, disconnect this edge and record the left and right endpoints (assuming mark1, mark2), and do dp for the left and right endpoints respectively (dp is the same as that question, students who have not done that question can do it first that question), dp[i][0] means not to take the maximum result of i in the subtree of i, dp[i][1] means to take the maximum result of i in the subtree of i, then the answer is max( dp[mark1][0],dp[mark2][0]). Why is this right? Let’s calmly analyze that mark1 and mark2 cannot be selected at the same time. dp[mark1][0] means that mark1 is not selected, and it does not matter whether mark2 is selected or not. The same is true for mark2, so we are equivalent to considering this perfectly. The effect of the edge on the answer, the correctness is obvious. (Note that there may be multiple connected blocks, add all the answers)


Specific methods:
1. Use union search to find an edge on the ring when reading in, and record the left and right endpoints (mark1, mark2)
2. Make tree dp for the left and right endpoints (note dp[mark1][0] and dp[mark2] ][0] is the result obtained by two dp respectively, not the value obtained in one dp)
3. Add ans to max(dp[mark1][0], dp[mark2][0]) and continue this process until all connected blocks are traversed


Code: (Note that bfs cannot be used for tree dp in this question. I used bfs before, thinking that the tree is a broom and can get stuck, but it turns out that it is not feasible QAQ)

#include <bits/stdc++.h>
using namespace std;

const int maxn=1e6+100;
struct stu
{
    int to,next;    
}road[2*maxn]; int first[maxn],cnt=0;
long long ans,dp[maxn][2],fa[maxn];
int n,val[maxn],mark1[maxn],mark2[maxn],cnt1=0;

void addedge(int x,int y)
{
    road[++cnt].to=y;
    road[cnt].next=first[x];
    first[x]=cnt;   
}

int find(int x)
{
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);   
}

void dfs(int now)
{
    dp[now][0]=0,dp[now][1]=val[now];
    for(int i=first[now];i;i=road[i].next)
    {
        int to=road[i].to;
        if(to==fa[now]) continue;
        fa[to]=now;
        dfs(to);
        dp[now][0]+=max(dp[to][0],dp[to][1]);
        dp[now][1]+=dp[to][0];  
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d%d",&val[i],&x);
        int p1=find(i),p2=find(x);
        if(p1==p2)
        {
            mark1[++cnt1]=i;
            mark2[cnt1]=x;
        }
        else 
        {
            fa[p1]=p2;
            addedge(i,x);
            addedge(x,i);
        }
    }
    for(int tt=1;tt<=cnt1;tt++)
    {
        long long nowans=0;
        memset(fa,0,sizeof(fa));
        memset(dp,0,sizeof(dp));
        dfs(mark1[tt]);
        nowans=dp[mark1[tt]][0];
        memset(fa,0,sizeof(fa));
        memset(dp,0,sizeof(dp));
        dfs(mark2[tt]);
        nowans=max(nowans,dp[mark2[tt]][0]);
        ans+=nowans;
    }
    printf("%lld\n",ans);
    return 0;   
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324673055&siteId=291194637