洛谷P1967 貨車運輸 MST,建樹,LCA

2021-09-25 01:30:32 字數 1746 閱讀 6564

題目:

分析:1、首先建立最大生成樹(可能是森林),常用的是kruskal演算法,需要借助並查集,採用前向星儲存mst。

2、上面的mst是無根的,需要轉換成有根的。引入三個陣列。deep[i]——結點i的深度;f[i][j]——結點i的2^j的遠祖;g[i][j]——結點i到它的2^j的遠祖路徑上的瓶頸值。在建樹的過程中採用遞推的方法求出d,f,g。

3、lca查詢x到y路徑上的瓶頸值。lca分三個經典步驟:一是用x表示深度大的點;二是move,用倍增的方法將x的深度調成與y一樣,如果更新的後的x=y,則對應的min即是所求(乙個細節);三是倍增求出最近公共祖先,有兩個細節需要注意。詳見**說明。

關於樹上倍增求lca的說明:

一、打表:(for要求順序)

用f[x][i]表示點x的2^i遠的祖先,有遞推式f[x][i]=f[ f[x][i-1] ][i-1],遍歷所有點,求出所有點的2^i的祖先,其中i=0..20。

二、查表:(for要求逆序)

1、用x表示深度大的點;

2、如果deep[x]!=deep[y],用倍增方法使得deep[x]=deep[y],如果x=y,則return lca=x(細節)

3、用倍增方法同步往上找,如果f[x][i]!=f[y][i](細節),則令x=f[x][i],y=f[y][i],結束查表後的x與y是lca的兒子,

故需要 return f[x][0](細節)

ac**:

#include#include#include#include#includeusing namespace std;

int n,m,q,head[10005],num,fat[10005];

bool vis[10005]=;

int deep[10005],f[10005][21],g[10005][21];

struct t;

t a[50005];

struct edge;

edge e[100005];

int cmp( t a, t b)

void add(int from,int to,int w)

int father(int x)

void unionn(int x,int y)

void kurskal()

}}void build_tree(int u)

for(int i=head[u];i!=-1;i=e[i].next)

}}int move(int &u,int h)

}return minn;

}int lca(int x,int y)

}

}if(x==y)return minn;//細節:重要,否則與下面for之後min所在行**衝突

for(int i=20;i>=0;i--)

if(f[x][i]!=f[y][i])

minn=min(minn,min(g[x][0],g[y][0]));//細節:注意:前面的for結束後x!=y

return minn;

}int main()

//查詢

cin>>q;

for(int x,y,i=1;i<=q;i++)

return 0;

}

洛谷 P1967 貨車運輸

a 國有 n 座城市,編號從 1 到 n,城市之間有 m 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有 q 輛貨車在運輸貨物,司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。輸入檔名為 truck.in。輸入檔案第一行有兩個用乙個空格隔開的整數 n,m,表示 a 國有 ...

洛谷 P1967 貨車運輸

題目描述 a 國有 n 座城市,編號從 1 到 n,城市之間有 m 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有 q 輛貨車在運輸貨物,司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。輸入輸出格式 輸入格式 輸入檔名為 truck.in。輸入檔案第一行有兩個用乙個空格隔...

貨車運輸 洛谷p1967

解法一 30分 直接跑spfa,求最大瓶頸路。include include include define f i,l,r for i l i r i using namespace std const int maxn 10005,maxm 50005,inf 100000000 struct e...