1. 程式人生 > >light oj 1257 Farthest Nodes in a Tree (II)(724訓練題目)主要是利用了反證法: 假設 s-t這條路徑為樹的直徑,或者稱為樹上的最長路 現有結論,從任意一點

light oj 1257 Farthest Nodes in a Tree (II)(724訓練題目)主要是利用了反證法: 假設 s-t這條路徑為樹的直徑,或者稱為樹上的最長路 現有結論,從任意一點

主要是利用了反證法:

假設 s-t這條路徑為樹的直徑,或者稱為樹上的最長路

現有結論,從任意一點u出發搜到的最遠的點一定是s、t中的一點,然後在從這個最遠點開始搜,就可以搜到另一個最長路的端點,即用兩遍廣搜就可以找出樹的最長路

證明:

1    設u為s-t路徑上的一點,結論顯然成立,否則設搜到的最遠點為T則

dis(u,T) >dis(u,s)     且  dis(u,T)>dis(u,t)   則最長路不是s-t了,與假設矛盾

2   設u不為s-t路徑上的點

    首先明確,假如u走到了s-t路徑上的一點,那麼接下來的路徑肯定都在s-t上了,而且終點為s或t,在1中已經證明過了

    所以現在又有兩種情況了:

    1:u走到了s-t路徑上的某點,假設為X,最後肯定走到某個端點,假設是t ,則路徑總長度為dis(u,X)+dis(X,t)

    2:u走到最遠點的路徑u-T與s-t無交點,則dis(u-T) >dis(u,X)+dis(X,t);顯然,如果這個式子成立,

    則dis(u,T)+dis(s,X)+dis(u,X)>dis(s,X)+dis(X,t)=dis(s,t)最長路不是s-t矛盾

    附上一張第二種情況的圖

這道題讓你求出距離每個點最遠的點之間距離是多少,因為每個點走的最長路的重點肯定是直徑上的某個端點,所以,寫個bfs不斷的搜吧

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<vector>
#define N 30005
#define in push_back
using namespace std;
vector<int>e[N];
vector<int>d[N];
int k,u,v,w,n,t;
int d1[N],d2[N];
bool b[N];
void bfs(int s,int &t,int w[])
{
   queue<int>q;int mx=0;
   memset(b,0,sizeof(b));
   memset(w,0,sizeof(w));
   q.push(s);b[s]=1;w[s]=0;
   while(!q.empty())
   {
      int now=q.front();q.pop();
      for(int i=0;i<e[now].size();i++)
      {
          v=e[now][i];if(b[v])continue;
          {
             w[v]=w[now]+d[now][i];
             b[v]=1;q.push(v);
             if(w[v]>mx) mx=w[v],t=v;
          }
      }
   }
}

int main()
{
    scanf("%d",&t);
    k=0;
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
          {e[i].clear();d[i].clear();}
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            e[u].in(v);e[v].in(u);
            d[u].in(w);d[v].in(w);
        }
        memset(d1,0,sizeof(d1));
        memset(d2,0,sizeof(d2));
        int x,y;
        bfs(0,x,d1);
        bfs(x,y,d1);
        bfs(y,x,d2);
        printf("Case %d:\n",++k);
        for(int i=0;i<n;i++)
        {
            printf("%d\n",max(d1[i],d2[i]));
        }
    }
}
方法2:對於每個點,維護一個最長路一個次長路,起初,由葉節點向根結點更新,記錄每個根結點是由哪個子節點更新的最長路,然後再做一遍dfs由根結點向子節點更新,對於一個子節點i,若其父節點的最長路是由其更新的,那麼在更新i的最、次長路時注意交叉問題,不需要加i到父節點邊長的不用加,對於每個i依然保留更新i最長路的父節點,若i不是更新父節點最長路的節點,方法照舊,然後依次向下dfs。

程式碼來自某大神~~~~

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
struct edge
{
    int v;
    int w;
    int next;
}edge[60010];
int head[30005];
int tot = 1;
void add(int u,int v,int w)
{
    edge[tot].v=v;
    edge[tot].next=head[u];
    edge[tot].w=w;
    head[u]=tot++;
}
int t,n,u,v,w;
int vis[30005];
int l1[30004],l2[30005];
long long cost1[30004],cost2[30004];
int num[30004];

void dfs(int u,int p)
{
    l1[u]=0;
    l2[u]=0;
    cost1[u]=0;
    cost2[u]=0;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        int w = edge[i].w;
        if(v==p) continue;
        dfs(v,u);
        if(cost2[u]<cost1[v]+w)
        {

            cost2[u]=cost1[v]+w;
            if(cost1[u]<cost2[u])
            {
               // swap(l1[u],l2[u]);
                swap(cost1[u],cost2[u]);
                num[u]=v;
            }
        }
    }
}
void dfs2(int u,int p)
{
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        int w = edge[i].w;
        if(v==p) continue;
        if(v==num[u])
        {
            if(cost2[v]<cost2[u]+w)
            {

                cost2[v]=cost2[u]+w;
                if(cost1[v]<cost2[v])
                {
                   // swap(l1[v],l2[v]);
                    swap(cost1[v],cost2[v]);
                    num[v]=u;
                }
            }
        }
        else
        {
            if(cost2[v]<cost1[u]+w)
            {
               // l2[v]=l1[u]+1;
                cost2[v]=cost1[u]+w;
                  if(cost1[v]<cost2[v])
                {
                    //swap(l1[v],l2[v]);
                    swap(cost1[v],cost2[v]);
                    num[v]=u;
                }
            }
        }
        dfs2(v,u);
    }
}
int main()
{
   scanf("%d",&t);
   int Case = 1;
   while(t--)
   {
       scanf("%d",&n);

       tot=1;
       memset(head,-1,sizeof(head));
       for(int i=1;i<n;i++)
       {
           scanf("%d%d%d",&u,&v,&w);
           add(u,v,w);
           add(v,u,w);
       }
       dfs(0,-1);
       dfs2(0,-1);
       printf("Case %d:\n",Case++);
       for(int i=0;i<n;i++)
       {           //printf("%d %lld %lld \n",i,cost1[i],cost2[i]);
           printf("%lld\n",cost1[i]);
       }
   }
    return 0;
}



相關推薦

light oj 1257 Farthest Nodes in a Tree (II)(724訓練題目)主要利用反證法 假設 s-t路徑直徑或者稱為樹上 現有結論任意一點

主要是利用了反證法: 假設 s-t這條路徑為樹的直徑,或者稱為樹上的最長路 現有結論,從任意一點u出發搜到的最遠的點一定是s、t中的一點,然後在從這個最遠點開始搜,就可以搜到另一個最長路的端點,即用兩遍廣搜就可以找出樹的最長路 證明: 1    設u為s-t路

light oj 1094 Farthest Nodes in a Tree直徑模板)

fas problems tro tree enter have () 分享 color 1094 - Farthest Nodes in a Tree PDF (English) Statistics Forum Time Limit: 2

[GeeksForGeeks] Populate inorder successor for all nodes in a binary search tree

stack iter pro get root following sin ice nod Given a binary search tree with the following tree node definition. next points to a node‘s

Lowest Common Ancestor of Two Nodes in a Binary Tree

Reference:http://blog.csdn.net/v_july_v/article/details/18312089  http://leetcode.com/2011/07/lowest-common-ancestor-of-a-binary-tree-part-ii.html(1) Is th

【CodeForces】914 E. Palindromes in a Tree 點分治

統計 bool truct oot print i++ rom tar edge 【題目】E. Palindromes in a Tree 【題意】給定一棵樹,每個點都有一個a~t的字符,一條路徑回文定義為路徑上的字符存在一個排列構成回文串,求經過每個點的回文路徑數。n&l

PAT甲1115 Counting Nodes in a BST【dfs】

1115 Counting Nodes in a BST (30 分) A Binary Search Tree (BST) is recursively defined as a binary tree which has the following prope

「日常訓練&知識學習」莫隊演算法(二)樹上莫隊(Count on a tree IISPOJ COT2)

題意與分析 題意是這樣的,給定一顆節點有權值的樹,然後給若干個詢問,每次詢問讓你找出一條鏈上有多少個不同權值。 寫這題之前要參看我的三個blog:CFR326D2E、CFR340D2E和HYSBZ-1086,然後再看這幾個Blog—— 參考A:https://blog.sengxian.com/algori

1115 Counting Nodes in a BST (30 分)

1115 Counting Nodes in a BST (30 分) A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties: The

PAT (Advanced Level) Practice 1115 Counting Nodes in a BST (30 分)

排序二叉樹,注意看定義 #include<cstdio> using namespace std; const int N=1e3+5; int ch[N][2],key[N],rt,dfn,level[N]; void insert(int x) { ke

CF914E Palindromes in a Tree(點分治)

https print 並且 單個 last strong lin efi const 題面 洛谷 CF 題解 題意:給你一顆 n 個頂點的樹(連通無環圖)。頂點從 1 到 n 編號,並且每個頂點對應一個在‘a’到‘t’的字母。 樹上的一條路徑是回文是指至少有一個對應字母的

LeetCode oj 237. Delete Node in a Linked List (連結串列)

Write a function to delete a node (except the tail) in a singly linked list, given only access to that node. Supposed the linked list is 1 -> 2 ->

PAT 1115 Counting Nodes in a BST

A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties: The left subtree of a node

一個字串A的子串被定義成A中順次選出若干個字元構成的串。如A=“cdaad" ,順次選135個字元就構成子串" cad" ,現給定兩個字串求它們的共公子串。 小王對既是素數又是迴文的

一個字串A的子串被定義成從A中順次選出若干個字元構成的串。如A=“cdaad" ,順次選1,3,5個字元就構成子串" cad" ,現給定兩個字串,求它們的最長共公子串。 小王對既是素數又是迴文的數特

HDU 3249 Test for job (有向無環圖上的DP)

code head struct sin == cout article scanf for ?? 解題思路: 求有向無環圖上的最長路。簡單的動態規劃#include <iostream> #include <cstring> #include

186. Reverse Words in a String II

defined pro etc pan log without rate null target 題目: Given an input string, reverse the string word by word. A word is defined as a seque

Count on a tree II

limit 時間 序號 time 就是 出現一次 ria sse 處理 You are given a tree with N nodes. The tree nodes are numbered from 1 to N. Each node has an integer

SPOJ.COT2 Count on a tree II(樹上莫隊)

main node return post logs ems truct pri spoj 題目鏈接(同上一題蘋果樹) 為什麽第10個點T了一晚上。。 下面那個卻AC了?跑的也不慢。 TLE: /* 在DFS序做莫隊 當一個點不是另一個點的LCA時,需要加上它們LCA的貢

SPOJCOT2 Count on a tree II

else date poj get typedef inline AD inpu %d 題意 給定一個n個節點的樹,每個節點表示一個整數,問u到v的路徑上有多少個不同的整數。 n=40000,m=100000 Sol 樹上莫隊模板題 # include <bits/s

SPOJ - COT2 Count on a tree II

amp 不同的 技術 edge class poj include push 方法 題意;   一棵N個節點的樹,有點權。M次詢問,每次詢問點(u,v)路徑上有多少個權值不同的點。 題解:   樹上開莫隊,分塊方法可以參照BZOJ1086題的方式。按照詢問點(u,v)所在塊

SPOJ COT2 - Count on a tree II(樹上莫隊)

DG 討論 The follow || SQ ren algorithm line 題目描述 給定一個n個節點的樹,每個節點表示一個整數,問u到v的路徑上有多少個不同的整數。 輸入格式 第一行有兩個整數n和m(n=40000,m=100000)。 第二行有n個整數。