&& diameter tree explanations P3629 [[APIO2010]] patrol

Although there are many Dalao sent a lot of very detailed explanations, but the konjac or (with the spirit of fearless) to send a solution to a problem.

Graph theory is because of the recent review of the original study,HappenIt is not clever) Saw this question, then ...... point came .

In fact, just to see this question when, still a little ignorant (of course, this is a graph theory did not have to run). Then, I'll scratch reason his thoughts.
First:
1, all roads on the map to be reached.
2, all operations are number one from the start point, end point number one.
3, to patrol such a short distance.

first step

We first consider the case without the side
starting from 01 points, each side should again traverse back to point 1, it will go through each edge exactly twice,General lineOh, no, after a total length of the route it is 2 (n-1).


The second step

Let's consider the case of k == 1.
The establishment of a new edge, because every new edge to be.

Just after one

Because this is a tree, so when we add an edge to form a ring, and this ring can make this figure may reduce duplication while traversing take sides. Figure (not veryVery ugly): 

 

 

The ring because of the reduction caused by repeated path, so we have to find a tree at this time in the longest chain in the construction of ring structure, so that we can meet the minimum solution on the question, this time we have to push formula :

2(n-1)-L+1
If you have already thought of this, then congratulations, you've successfully got 30 points. AC Let's look at how this question.


third step

After the completion of the first road was built, we consider the second way. When the new second path (u, v) establishing, will form a ring. When not even a ring overlapping the time, the answer would have been reduced. But if there are overlapping portions, there will not be a part of the road to patrol, so we had to re-patrol car on this side, and finally return. This operation eventually make that edge after repeated once.
Specifically Figure: 

 

In this case, we get the shortest path.
Summarize the specific steps:
1, first find the diameter of the tree in the original tree, denoted L1, then the right side to -1 (-1'll explain why later).
2, after the inverted edge weight of the tree to find again a diameter denoted as L2.
3. Calculate the answer.

official

From the foregoing explanation can be inferred:

= ANS 2 (N- . 1 ) - (Ll- . 1 ) - (the L2- . 1 ) 
i.e. 
ANS = 2N-Ll-L2 of

 

Time complexity, then it is very intuitive O (n).


On the front of the train of thought to explain here, let's talk about the code.

First of all

This question is one of the most intuitive test center - the diameter of the tree
so the following will explain the test center of the tree diameter.
Is simply the diameter of the tree is the longest chain of the tree, the two O (n) method below to find the diameter of the tree.
BACKGROUND: N-1 hypothesis tree edges is given is given in the form of a table adjacent to the N nodes in a non-directed graph.

The first: the diameter of the tree Tree request DP

We use the distance d [x], f [x ] is the distance between any two points represented.
Code:

void dp(int x){
    v[x]=1;
    for(int i=head[x];i;i=e[i].next){
        int y=e[i].to;
        if(v[y])continue;
        dp(y);
        ans=max(ans,dis[x]+dis[y]+e[i].w);
        dis[x]=max(dis[x],dis[y]+e[i].w);
    }
}

Dp with a tree to solve the case, a very significant advantage is that we can deal with the problem of negative rights system


The second: BFS twice the diameter of the tree's beg

Diameter determined by two BFS, the diameter of the particular node more in diameter is calculated.
Step:
① any departure from the tree point P, the distance to find its maximum point M
from the point M ②, find their greatest distance from point N of
the diameter of the tree is the ③MN
following is a specific proof (proof taken from the teacher ppt).

Contradiction: Suppose M is not an endpoint in diameter, AB is the diameter of the tree.

① If P is a point on a diameter, as shown, PM> PB is AP + PM> AP + PB = AB and AB is the diameter of this contradiction. 

 

②-1 If P is not diametrically: P M to path A to the path B have the common node TPT + TM> PT + TB, the TM> TB, so the AT + TM> AT + TB = AB, conflicts

 

②-2 P to path A M to path B have no common junction PC + CM> PC + CD + BD, the CM> CD + BD, CM + CD> BD so CM + CD + AD> BD + AD = AB, contradictory.

 



BFS on both sides of the correctness of such proof is completed.
Code:

 1 void bfs(int x,int ck){
 2     memset(dis,0,sizeof(dis));
 3     memset(vis,0,sizeof(vis));
 4     queue<int >q;
 5     q.push(x);
 6     vis[x]=1;
 7     while(!q.empty()){
 8         int now=q.front();
 9         q.pop();
10         for(int i=head[now];i;i=e[i].next){
11             int y=e[i].to;
12             if(!vis[y]){
13                 vis[y]=1;
14                 dis[y]=dis[now]+e[i].w;
15                 q.push(y);
16                 if(ck)f[y]=now;//记录父节点,修改时会用
17             }
18         }
19     }
20     for(int i=1;i<=n;i++){
21         if(ans<dis[i])ans=dis[i],point=i;
22     }
23 }

 

 

两遍BFS求树的直径的优点很明显,但是缺点也很突出,就是无法处理负权值。
所以我们在处理过第一次的直径后将权值赋为了-1,就是这个原因。
下面就是这道题的AC代码了

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 template<typename type>
  4 void scan(type &x){
  5     type f=1;x=0;char s=getchar();
  6     while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
  7     while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
  8     x*=f;
  9 }
 10 const int N=1e5+7;
 11 struct node{
 12     int to,w,next;
 13 }e[N*2];
 14 int head[N],cnt;
 15 void add(int a,int b,int c){
 16     e[++cnt].to=b;
 17     e[cnt].next=head[a];
 18     head[a]=cnt;
 19     e[cnt].w=1;
 20 }
 21 int dis[N],vis[N],l1,l2,n,k,point,f[N],d[N],v[N];
 22 int ans=0;
 23 void bfs(int x,int ck){
 24     memset(dis,0,sizeof(dis));
 25     memset(vis,0,sizeof(vis));
 26     queue<int >q;
 27     q.push(x);
 28     vis[x]=1;
 29     while(!q.empty()){
 30         int now=q.front();
 31         q.pop();
 32         for(int i=head[now];i;i=e[i].next){
 33             int y=e[i].to;
 34             if(!vis[y]){
 35                 vis[y]=1;
 36                 dis[y]=dis[now]+e[i].w;
 37                 q.push(y);
 38                 if(ck)f[y]=now;//记录父节点,修改时会用
 39             }
 40         }
 41     }
 42     for(int i=1;i<=n;i++){
 43         if(ans<dis[i])ans=dis[i],point=i;
 44     }
 45 }
 46 void change(int a){//修改边权值
 47     while(f[a]){
 48         int fa=f[a];
 49         for(int i=head[fa];i;i=e[i].next){
 50                 // e[i].w=-1;
 51                 if(e[i].to==a){
 52                 //    e[i].w=e[i^1].w=-1;
 53                    e[i].w=-1;
 54                    break; 
 55                 }
 56         }
 57         for(int i=head[a];i;i=e[i].next){
 58             if(e[i].to==fa){
 59                 e[i].w=-1;
 60                 break;
 61             }
 62         }
 63         a=fa;
 64     }
 65 }
 66 void dp(int x){
 67     v[x]=1;
 68     for(int i=head[x];i;i=e[i].next){
 69         int y=e[i].to;
 70         if(v[y])continue;
 71         dp(y);
 72         ans=max(ans,dis[x]+dis[y]+e[i].w);
 73         dis[x]=max(dis[x],dis[y]+e[i].w);
 74     }
 75 
 76 }
 77 
 78 int main(){
 79    scan(n);scan(k);
 80     // scanf("%d%d",&n,&k);
 81     for(int i=1;i<n;i++){
 82         int a;int b;
 83        scan(a);scan(b);
 84         // scanf("%d%d",&a,&b);
 85         add(a,b,1);
 86         add(b,a,1);
 87     }
 88     if(k==1){
 89         bfs(1,0);
 90         bfs(point,0);
 91         printf("%d",2*n-dis[point]-1);
 92     }else{
 93         bfs(1,0);
 94         bfs(point,1);
 95         l1=dis[point];
 96         change(point);
 97         memset(dis,0,sizeof(dis));
 98         memset(vis,0,sizeof(vis));
 99         ans=0;
100         dp(1);
101         // printf("%d\n",l1);
102         // printf("%d\n",ans);
103         printf("%d",2*n-ans-l1);
104     }
105     return 0;
106 }
View Code

 

希望大家关注一波。

Guess you like

Origin www.cnblogs.com/xishirujin/p/11104303.html
Recommended