[BZOJ3743] [Coci2015] Kamp solution to a problem

bzoj URL link? ?

Meaning of the questions:

A \ (n-\) nodes of the tree, above \ (K \) key points, through each side requires a certain weight, seeking \ ([1, n] \ ) from each starting point, after all key points, not back to square one, through which the path of minimum weight and value.

data range:


50 minutes: \ (O (^ n-2) \)

  • Finally, consider the return to the source case, then each is a need to go side to go through twice, no matter how you go all the same. And so only the requirements, and the current source to a certain critical point of the longest path, to subtract (minus the last back away) need to go all sides.

  • A current source to a key point of the longest path well ask, \ (the DFS \) just once.

As shown, the blue dot to the current source, the red dot keys.

  • The so-called need to take sides, that is rough edges in the graph can be found by observing, as a side rough edges, if and only if the subtree this edge connection sons have key points .

  • So just find the key points in each sub-tree when each source point to the \ (cnt \) , to traverse time statistics about enough. Time complexity \ (O (n ^ 2) \)

Key Code:

struct cut1{
    int s[2005],dp[2005],mark[2005],suml,mx;
    void dfs(int x,int f,int d){
        if(mark[x]&&d>mx)mx=d;//求最长路径
        if(mark[x])dp[x]=1;
        for(int i=0;i<edge[x].size();i++){
            int y=edge[x][i].to,z=edge[x][i].v;
            if(y==f)continue;
            dfs(y,x,d+z);
            if(dp[y]!=0)suml+=z;//统计所有要走到的边
            dp[x]+=dp[y];
        }
    }
    void solve(){
        for(int i=1,x;i<=k;i++){
            scanf("%d",&x);//输入关键点
            mark[x]=1;
        }
        for(int i=1;i<=n;i++){
            memset(dp,0,sizeof(dp));
            suml=0;mx=0;
            dfs(i,0,0);
            printf("%d\n",suml*2-mx);
        }
    }
}P50;

100: \ (O (m) \) from the idea of extending from 50 minutes

And 50 points, will have two major problems:

  • Each point is determined to a certain critical point of a longest path

  • Each point is determined to be traversed through the edge (edge ​​and crude)

For the second question , a solution to a problem already explained very well. . .

Defined in \ (X \) is the rough edges and root to \ (SUM [X] \) , \ (Y \) is the \ (X \) son, discussion can be divided into the following three categories:

Specific details can reference code.


As to the first question, I heard very classic,I have not heard, The idea is that the tree DP

Under each node in mind it to its critical point of the path subtree maximum value and the time length value .
This is better achieved, once \ (dfs \) can be.

Note: The maximum value and Minister value is not in the strict sense, but for each node, from its two different sons came in. It will explain the specific reasons behind.

We longest path point to a critical point of discussion into two parts: the outer key of the key points in the sub-tree and the subtrees.

Separately, see the code:

#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<endl
#define LL long long
using namespace std;
bool cur1;
const LL N=500005,inf=1e9;
struct node{LL to,v;};
vector<node>edge[N];
LL n,K;
LL mx[N][2],mxf[N],cnt[N],sum[N],tmx[N],st[N],top,fa[N],mark[N];
void dfs(LL x,LL f){
    fa[x]=f;mx[x][0]=mx[x][1]=mxf[x]=-inf;
    if(mark[x]){
        mx[x][0]=0;
        cnt[x]=1;
    }
    st[++top]=x;
    for(LL i=0;i<edge[x].size();i++){
        LL y=edge[x][i].to,z=edge[x][i].v;
        if(y==f)continue;
        dfs(y,x);
        cnt[x]+=cnt[y];
        if(cnt[y]){
            sum[1]+=z;
            LL nw=mx[y][0]+z;
            if(nw>=mx[x][0]){
                tmx[x]=y;
                mx[x][1]=mx[x][0];
                mx[x][0]=nw;
            }
            else if(nw>mx[x][1])mx[x][1]=nw;
        }
    }
}
void solve(){
    for(LL i=1;i<=n;i++){
        LL x=st[i];
        for(LL j=0;j<edge[x].size();j++){
            LL y=edge[x][j].to,z=edge[x][j].v;
            if(y==fa[x])continue;
            if(cnt[y]==K)sum[y]=sum[x]-z;
            else if(cnt[y]==0)sum[y]=sum[x]+z;
            else sum[y]=sum[x];
            if(tmx[x]==y)mxf[y]=max(mxf[x],mx[x][1])+z;
            else mxf[y]=max(mxf[x],mx[x][0])+z;
        }
    }
    for(LL i=1;i<=n;i++)
        printf("%lld\n",sum[i]*2-max(mxf[i],mx[i][0]));
}
bool cur2;
int main(){
    scanf("%lld%lld",&n,&K);
    for(LL i=1,x,y,z;i<n;i++){
        scanf("%lld%lld%lld",&x,&y,&z);
        edge[x].push_back(node<%y,z%>);
        edge[y].push_back(node<%x,z%>);
    }
    for(LL i=1,x;i<=K;i++){
        scanf("%lld",&x);
        mark[x]=1;
    }
    dfs(1,0);
    solve();
    return 0;
}

Guess you like

Origin www.cnblogs.com/tangzhiyang/p/11804689.html