前置知識:生成樹,並查集,倍增求lca
化簡題意:求圖上兩點之間路徑上邊權最小的邊(由於最終生成的是樹,所以路徑唯一)。注意兩點可能是不連通的。
大致:先用最大生成樹重新建邊,然後用並查集判斷一下兩點是否在同乙個聯通塊,之後用倍增在求lca的時候維護邊權的最小值
最大生成樹:由於要找邊權最小的邊,所以盡量在生成樹的時候選大邊(sort排序改一下就行了)
並查集:生成樹使用克魯斯卡爾演算法,因為從資料可以得出是稀疏圖,不建議使用皮姆演算法其實是我不會
#include
using
namespace std;
int n,m,q;
struct _edge1pe[
100007];
//原圖
struct _edge2ne[
100007];
//重新建的圖
int num_edge2,nh[
100007];
//鏈式前向星
int mst_fa[
10007];
//並查集
int bz_fa[
10007][
21],minn[
10007][
21],dep[
10007
],vis[
10007];
//倍增求lca
void
add_edge2
(int x,
int y,
int w)
;//前向星加邊
intread()
;//快讀
//mst最小生成樹部分
intmst_find_fa
(int x)
void
mst_merge
(int x,
int y)
bool
cmp(_edge1 x,_edge1 y)
void
mst()}
return;}
//mst
//dfs
void
dfs(
int now)
return;}
//dfs
//lca
intlca
(int x,
int y)}if
(x==y)
return ans;
for(
int i=
14;i>=0;
--i)
if(bz_fa[x]
[i]!=bz_fa[y]
[i])
ans=
min(ans,
min(minn[x][0
],minn[y][0
]));
//記得最後還要求一次(其實這裡[x][0]和[y][0]選乙個取最小就行了,因為已經是公共祖先)
return ans;
//最後就不是返回祖先了,而是邊權最小值
}//lca
intmain()
mst();
for(
int i=
1;i<=n;
++i)
}for
(int j=
1;j<=14;
++j)
for(
int i=
1;i<=n;
++i)
cin>>q;
for(
int i=
1;i<=q;
++i)
return0;
}//add_edge
void
add_edge2
(int u,
int v,
int w)
//add_edge
//read
intread()
while
(ch>=
'0'&&ch<=
'9')
return res*flag;
}//read
洛谷 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...