先對所有的路徑求取lca,然後按照lca從大到小的順序選取路徑
若一條路徑p1的lca(p1) 的深度大於p2的lca(p2),那麼若p1和p2出現衝突,那麼p1一定包含p2的lca(p2),那麼p2只可能與以lca(p2)為子樹中的路徑衝突,而p1要衝突的範圍更大,兩個的貢獻同樣是1,如果存在一棵比lca(p1)和lca(p2)深度都大的子樹中的子樹中路徑,如果它和p1不衝突,卻和p2衝突,那麼它已經將p2淘汰,但不會影響p1的選取,所以當前貪心策略是正確的.
#include #include #include #include #define max 200007
using namespace std;
int ce , cq;
struct edge
e[max<<1];
struct query
}q[max<<1];
int head1[max];
int head2[max];
int depth[max];
void adde ( int u , int v )
void addq ( int u , int v )
int fa[max];
int find ( int x )
void lca ( int u = 1 , int p = -1 )
for ( int i = head2[u] ; i != -1 ; i = q[i].next )
} bool vis[max];
int pa[max];
void dfs ( int u = 1 , int p = -1 , int deep = 1 )
}void paint ( int i , int u )
bool judge ( int i , int u )
u = q[i].v;
while ( u != lca )
if ( vis[lca] ) return false;
return true;
}int main ( )
for ( int i = 0 ; i < m ; i++ )
dfs ();
lca ();
sort ( q , q+2*m );
int ans = 0;
// for ( int i = 1 ; i <= n ; i++ )
// cout << i <<" : " << pa[i] << endl;
for ( int i = 0 ; i < cq ; i++ )
// for ( int i = 1 ; i <= n ; i ++ )
// cout << vis[u] << " ";
// cout << endl;
}printf ( "%d\n" , ans );
}}
hdu 4912 終於解脫了
歷經n發wa之後 終於解脫了 這感覺.無法言表.其實 這題你說難吧?對於我而言 一共就做過一道lca的人來說 是有點難的 可是吧 當你慢慢地寫下來 其實 那麼長 又不怎麼難 對於此題 就是先求出query中2個結點的lca之後 然後dfs它們的lca 根據深度進行排序 這個其實不難理解吧?當然深度越...
最近公共祖先 python 最近公共祖先
lca演算法樸素演算法 也就是我們所說的暴力演算法,大致的思路是從樹根開始,往下迭代,如果當前結點比兩個結點都小,那麼說明要從樹的右子樹中找 相反則從左子樹中查詢 直到找到乙個結點在當前結點的左邊,乙個在右邊,說明當前結點為最近公共祖先,如果乙個結點是另外乙個結點的祖先,那麼返回前面結點的父親結點即...
最近公共祖先 LCA 最近公共祖先
直接暴力搜尋參考 普通搜尋每次查詢都需要 樸素演算法是一層一層往上找,倍增的話直接預處理出乙個 具體做法是 維護乙個 的關係來線性求出這個陣列 int anc n 31 int dep n 記錄節點深度 void dfs int u,int parent for int i 0 i g u size...