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不斷的搜吧
方法2:對於每個點,維護一個最長路一個次長路,起初,由葉節點向根結點更新,記錄每個根結點是由哪個子節點更新的最長路,然後再做一遍dfs由根結點向子節點更新,對於一個子節點i,若其父節點的最長路是由其更新的,那麼在更新i的最、次長路時注意交叉問題,不需要加i到父節點邊長的不用加,對於每個i依然保留更新i最長路的父節點,若i不是更新父節點最長路的節點,方法照舊,然後依次向下dfs。#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])); } } }
程式碼來自某大神~~~~
#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 II,SPOJ 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" ,順次選1,3,5個字元就構成子串" 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的貢
SPOJ:COT2 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個整數。