1. 程式人生 > 實用技巧 >題解 洛谷P3128 【[USACO15DEC]Max Flow P】

題解 洛谷P3128 【[USACO15DEC]Max Flow P】

\[\huge\mathcal{Description} \]

日期 2020年8月25日
編號 \(\texttt{洛谷P3128}\)
演算法 最近公共祖先(LCA)樹上差分
來源 \(USACO\ 2015\)

\[\huge\mathcal{Solution} \]

這道題目我們可以用樹上差分來解決。
這是一道樹上的點差分,需要統計每個點經過了多少次。
那麼我們不妨使用樹上差分,將每一次的路徑上的點加一。
這樣就可以很快得到每個點經過的次數。
再結合倍增法求出\(LCA\),最後\(DFS\)遍歷整棵樹,在回溯時對差分陣列求和就能求得答案了。

\[\huge\mathcal{Code} \]

#include<bits/stdc++.h>
#define MAX 50001
using namespace std;
struct Struct
{
    int To;
    int Next;
};
Struct Edge[2*MAX];
int TotalPoint,TotalEdge;
int Deep[MAX];
int Jump[MAX][31];
int Head[2*MAX];
int Prefix[MAX];
int Count;
int Ans;
inline void AddEdge(int U,int V)
{
    Edge[Count].To=V;
    Edge[Count].Next=Head[U];
    Head[U]=Count++;
}
inline void Dfs(int Now,int Father)
{
    register int i;
    Deep[Now]=Deep[Father]+1;
    Jump[Now][0]=Father;
    for(i=1;(1<<i)<=Deep[Now];i++)
    {
        Jump[Now][i]=Jump[Jump[Now][i-1]][i-1];
    }
    for(i=Head[Now];~i;i=Edge[i].Next)
    {
        register int Next;
        Next=Edge[i].To;
        if(Next==Father)
        {
        	continue;
        }
        Dfs(Next,Now);
    }
}    
inline int GetLCA(int A,int B)
{
    if(Deep[A]>Deep[B])
    {
        swap(A,B);
    }
    register int i;
    for(i=30;i>=0;i--)
    {
        if(Deep[A]<=Deep[B]-(1<<i))
        {
            B=Jump[B][i];
        }
    }
    if(A==B)
    {
        return A;
    }
    for(i=30;i>=0;i--)
    {
        if(Jump[A][i]==Jump[B][i])
        {
            continue;
        }
        A=Jump[A][i];
        B=Jump[B][i];
    }
    return Jump[A][0];
}
inline void GetAns(int Now,int Father)
{
	register int i;
	for(i=Head[Now];~i;i=Edge[i].Next)
	{
		register int Next;
		Next=Edge[i].To;
		if(Next==Father)
		{
			continue;
		}
		GetAns(Next,Now);
		Prefix[Now]+=Prefix[Next];
	}
	Ans=max(Ans,Prefix[Now]);
}
int main(void)
{
	register int i;
	cin>>TotalPoint>>TotalEdge;
	memset(Head,-1,sizeof(Head));
	for(i=1;i<TotalPoint;i++)
	{
		register int U,V;
		cin>>U>>V;
		AddEdge(U,V);
		AddEdge(V,U);
	}
	Dfs(1,0);
	for(i=1;i<=TotalEdge;i++)
	{
		register int U,V;
		cin>>U>>V;
		register int LCA;
		LCA=GetLCA(U,V);
		Prefix[U]++;
		Prefix[V]++;
		Prefix[LCA]--;
		Prefix[Jump[LCA][0]]--;
	}
	GetAns(1,0);
	cout<<Ans<<endl;
	return 0;
}