Recent common ancestor synthesis algorithm notes

Original link
the original title link

Title Description

State-owned H n cities, cities with the n n-1 bidirectional path interconnected constitutes a tree, No. 1 is the capital city, is also the root of the tree.

H capital of the country broke out the dangers of a high infectious disease.

Authorities in order to control the epidemic, to prevent spread of the epidemic (city leaf nodes represented) border city, decided to use military force to establish checkpoints in some cities, so that from the capital to the border city of each path has at least one checkpoint, border cities can also create a checkpoint.

But it notes that the capital can not be established checkpoints.

Now, in some cities in the country H has stationed troops there, and a city could be stationed more troops.

The total number of troops to support m.

An army can move between road links to the city and to establish checkpoints in any city other than the capital, and only a checkpoint in the city.

An army after a road move from one city to another city needed time equal to the length of the road (unit: hour).

I ask you: How many hours to the minimum needed to control the epidemic?

Note: Different forces can move simultaneously.

Input Format

A first line integer n, the number of cities.

The next n-1 lines of three integers, u, v, w, between each two integers separated by a space, u represents from city to city v w has a length of road, ensure that the input data is a tree, and the root node number is 1.

The next line an integer m, indicates the number of forces.

The next line of m integers, each between two integers separated by a space, respectively, these m army stationed in the city's number.

Output Format

A total of one line containing an integer that represents the minimum time to control the epidemic needs. If you can not control the epidemic output -1.

data range

\ (2 \ m \ n \ the 50000 \) ,
\ (0 <w <10 ^ 9 \)

Sample input:

4
1 2 1
1 3 2
3 4 3
2
2 2

Sample output:

3

Sample Pictures

Epidemic control 2.png

Report problem-solving

Understand the meaning of problems

有一种传染病,叫做延迟快乐. by 秦淮岸灯火阑珊

Acwing site , we think it is a vividly \ (n-1 \) node of the tree.

Now from the root node ( YXC appear live between) at such a happy called delayed infectious diseases. He will infect the whole tree .

Now known to have \ (m \) administrator, they want to keep the new members (leaf nodes) are also infected with this delay happy infections, so they will be stationed in between some of the live separately.

(You can think of each room is a live node, and between a large live room is composed of many small live ,This is why, I do not know.)

Between every two live, there is a link, the link is different, they need data usage is not the same of.

Each administrator beginning to stay a different studio . They can and shuttle connected to each other to live among their own lies between live.

Now we want traffic consumes the largest consumption administrator minimum flow , so that the epidemic does not spread to new members (leaf node) body.

Administrators can not be stationed at the root node.Because the owners yxc has the highest authority, and now he has also been delayed infected happy. Not to be infected with other administrators can not reach yxc live among

If not possible to prevent delays Happy infectious diseases, then we can only output \ (--1 \) .

The strongestadpromoter

Ignorant feel good to force ah, we still nice to see the original meaning of the title bar.


Parsing algorithm

· Greedy nature to go up

Let's analyze this question in earnest purpose, contains a huge number of properties .

  1. All administrators, to the more advanced among the better go live.

Decent language, is that all of the control node, try to go to the root of the tree .

Why is this.

We know that an administrator, he faces three major choice .

going upTo make progress,go downComplacency, Do not go.Lounger

Our Acwing administrator, all of them are big brothers to make progress, they certainly will be going up .

However, this is why ?

A management node, he can control the range, in fact, is his son tree.

Infectious diseases are happy because of the delay comes from the root.

And each node, in fact, are the root node of the tree to his son's only channel .Can be said that the only middlemen .

So we have more going up, the more sub-tree node, then the greater the scope of management.

This is our first greedy nature.


Multi-monotonous nature of traffic

If you say that we are the richest (consume the most traffic) administrator, he consumed traffic is \ (the X-\) GB. To complete the task.

Then we give this administrator \ (x + 250G \) traffic, of course, he can complete the task.

But if we give him \ (x-1G \) traffic, then he could not complete the task.

To sum up, in short, we got, monotonous nature

If we say that the answer is x, then x-0.233 must not complete the task, x + 0.233 will be able to complete the task.


• Two people classified nature

We found that, in fact, all administrators can be divided into two groups.

  1. Able to reach the root node following son
  2. You can not reach the root node following son

We found that if an administrator administrator belongs to the second type, which is the best I could administrator, then obviously he arrived he could reach the depth of the shallowest node can be.

Greedy nature of the above can be obtained in accordance with, the more sub-tree node, then the greater the scope of management, we want to make the scope of management is the bigger the better. Therefore administrators more to walk on, but better, after all, manage to space the greater the.

Next we focus on analysis, first class administrator, referred to as the school has spare capacity of an administrator, then we find that the administrator, is facing two major life choice.

  1. Law-abiding , manage their own third of an acre tree subtree. That isFudo,Without any changes, still stay in this node .
  2. Transfer the workplace and seize all opportunities that can be controlled, leave yourself this node, through the root, we went to the other nodes, additional management subtree. .

In fact, we can also understand that a job is to stick to the original company, the other is switched to change to another company.

The current question is, how do we judge an administrator, is the law-abiding, or the transfer of the workplace.

We should have a basis for evaluation .

Let's take a good look at a picture.

Epidemic control .png

观察这张图片,我们非常清楚地发现.
\[ dis[1->2]>dis[1->3]>dis[1->4] \\\\ dis[a->b]表示节点a到节点b的距离 \]
假如说现在,\(2\)\(3\)这两个节点上面有管理员,然而节点\(4\)上面没有管理员,需要派遣管理员.

我们到底是派遣哪一个节点上的管理员去比较好呢?
\[ 如果处于2号节点的管理员他还有cnt \quad GB的流量 \\\\ 但是cnt < dis[1->2]+dis[1->2] \]
那么这位管理员,绝对不能够动,现在他处于极其重要的战略位置.

假如说这位管理员转移到其他节点的话,那么一定是转移到\(4\)号节点,因为
\[ dis[2->1]<dis[1->4] \]
这样我们才能够在流量不欠费的前提下,抵达目标节点.

但是我们知道目标节点,其实还可以由\(3\)号节点转移过来的,而且消耗的时间更加少.

那么我们把\(4\)号节点留给其他人,可能性更加多.

Or we understand this image, this node, if the administrator is gone, then there must be another administrator to fill across the root, this is clearly not good enough, not as good as another administrator stationed \ (4 \) No. Node then the administrator to stay down, so it takes even less, more excellent,

All in all, words and short, we identified the following scenario.

For a node needs stationed, we send fewer administrators to manage residual flow nearer the root node (the premise is that the administrator can reach this node).

That is a small capacity administrator, to manage nodes consume small, large capacity administrator, went to manage consumption of nodes.


Summary process
  1. Multiplying jump , climb quickly as possible so that all nodes

  2. Analyzing half , minimizing the maximum time consuming.

  3. Greedy allocation , so that it can make the best.


Code analysis

#include <bits/stdc++.h>
using namespace std;
#define mk(a,b) make_pair(a,b)
const int N=50000+200;
int head[N<<1],ver[N<<1],Next[N<<1],edge[N<<1],tot;
int deep[N],fa[N][22],cnt,n,m,a[N],sum;
int tot2,tot3,tot4,t;
long long dis[N][22],Free[N],need2[N];
bool vis[N],okk,need[N];
pair<long long,int> h[N];//可以抵达根节点的节点
struct Edge
{
    inline void init()
    {
        memset(head,0,sizeof(head));
        tot=0;
    }
    inline void add_edge(int a,int b,int c)
    {
        edge[++tot]=b;
        ver[tot]=c;
        Next[tot]=head[a];
        head[a]=tot;
    }
    inline void bfs()
    {
        queue<int> q;
        q.push(1);
        deep[1]=1;
        while(q.size())
        {
            int x=q.front();
            q.pop();
            for(int i=head[x]; i; i=Next[i]) //遍历x的出边
            {
                int y=edge[i];//出边
                if(deep[y])//已经访问过了 ,其实就是父亲节点
                    continue;//若深度小于当前节点,说明是当前节点的父节点
                deep[y]=deep[x]+1;//深度+1,儿子节点是y,父亲节点是x
                fa[y][0]=x,dis[y][0]=ver[i];//DP状态
                for(int j=1; j<=t; j++)
                {
                    fa[y][j]=fa[fa[y][j-1]][j-1];
                    dis[y][j]=dis[y][j-1]+dis[fa[y][j-1]][j-1];
                }//DP
                q.push(y);
            }
        }
    }
    inline bool dfs(int x)
    {
        bool ok=false;//判断是不是叶子节点,false为叶子,true为非叶子节点
        if (vis[x])//已经控制了
            return true;
        for(int i=head[x]; i; i=Next[i])//访问所有的出边
        {
            int y=edge[i];//出边节点
            if (deep[y]<deep[x])//比自己深度小的节点,那就是自己的父亲节点
                continue;
            ok=true;//既然有儿子节点了,那么一定不是叶子节点
            if (!dfs(y))//有叶子节点没有被控制,自己肯定也就不会被控制了
                return false;
        }
        if (!ok)//这个节点是叶子节点,而且没有被控制
            return false;
        return true;//所有叶子节点都被控制
    }
    inline bool check(long long s)
    {
        memset(h,0,sizeof(h));
        memset(need,0,sizeof(need));
        memset(vis,false,sizeof(vis));
        memset(need2,0,sizeof(need2));
        memset(Free,0,sizeof(Free));
        tot2=tot3=tot4=0;
        for(int i=1; i<=m; i++) //分类
        {
            long long ans=0,x=a[i];
            for(int k=t; k>=0; k--) //倍增跳跃
                if (fa[x][k]>1 && ans+dis[x][k]<=s)//找到最高能跳到哪里,且不会跳到根节点
                    ans+=dis[x][k],x=fa[x][k];//累加路径长度,并且跳跃
            if (fa[x][0]==1 && ans+dis[x][0]<=s)//跳到了根节点的儿子节点,有剩余时间
                h[++tot2]=mk(s-(ans+dis[x][0]),x);//剩余时间,当前位置
            else
                vis[x]=true;//位置x已经访问
        }
        for(int i=head[1]; i; i=Next[i])
            if (!dfs(edge[i]))
                need[edge[i]]=true;//开始遍历整棵树,康康有哪些节点没有被控制
        sort(h+1,h+1+tot2);//从小到大排序,剩余时间(第一维)
        for(int i=1; i<=tot2; i++) //空闲节点开始出发
            if (need[h[i].second] && h[i].first<dis[h[i].second][0])//你所在的节点需要控制,你抵达不了根节点,而且返回.
                need[h[i].second]=0;//去除标记,这支军队不动,继续驻守
        //我们之前已经剪掉过一次 详情请见s-(ans+dis[x][0]),所以这一次只要比较一下.就是剪掉两次的意思.
            else//可以调动
                Free[++tot3]=h[i].first;//存储空余时间 ,军队可以调动
        for(int i=head[1]; i; i=Next[i])
            if (need[edge[i]])//这个节点需要控制
                need2[++tot4]=dis[edge[i]][0];//需要控制的时间
        if (tot3<tot4)//军队不够用
            return false;
        sort(Free+1,Free+1+tot3);//军队按照空余时间(能力)从小到大排序
        sort(need2+1,need2+1+tot4);//需要驻守节点按照所需代价从小到大排序(驻守就是控制的意思)
        int i=1,j=1;//i表示需要驻守节点,j表示当前军队
        while(i<=tot4 && j<=tot3)//军队没有用完,节点没有走完
            if (Free[j]>=need2[i])
                i++,j++;
            else
                j++;
        if (i>tot4)//全部都驻守完了
            return true;
        else
            return false;
    }
    inline long long Point(void)
    {
        long long l=1,r=sum,mid=0;//二分边界
        while(l<r)
        {
            mid=l+r>>1;
            if (check(mid))
            {
                r=mid;
                okk=true;
            }
            else
                l=mid+1;
        }
        return r;
    }
} g1;
int main()
{
    g1.init();
    scanf("%d",&n);
    for(int i=1; i<n; i++)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        g1.add_edge(a,b,c);
        g1.add_edge(b,a,c);
        sum+=c;//统计所有边权之和
    }
    scanf("%d",&m);
    for(int i=1; i<=m; i++)
        scanf("%d",&a[i]);
    okk=false;
    t=log2(n)+1;
    g1.bfs();
    long long ans=g1.Point();
    printf("%lld\n",okk?ans:-1);
    return 0;
}

Guess you like

Origin www.cnblogs.com/gzh-red/p/11247112.html