洛谷1967 貨車運輸

2021-07-24 07:33:12 字數 3518 閱讀 4166

to神犇:請自動跳過前

x行的吐槽,因為吐槽內容可能只是一些極其無聊的

bug和友情提示……

codevs

上的資料略水(水了

8個點……),洛谷資料和官方一致。

題目描述

a 國有n

座城市,編號從1 到

n,城市之間有

m 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有

q 輛貨車在運輸貨物,

司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。

輸入輸出格式

輸入格式:

輸入檔名為

truck.in

。輸入檔案第一行有兩個用乙個空格隔開的整數n,

m,表示

a 國有

n 座城市和

m 條道

路。接下來

m 行每行

3 個整數x、

y、z,每兩個整數之間用乙個空格隔開,表示從

x 號城市到

y 號城市有一條限重為

z 的道路。意:

x 不等於

y,兩座城市之間可能有多條道路。

接下來一行有乙個整數

q,表示有

q 輛貨車需要運貨。

接下來q

行,每行兩個整數x、

y,之間用乙個空格隔開,表示一輛貨車需要從

x 城市運輸貨物到

y 城市,注意:

x不等於y。

輸出格式:

輸出檔名為

truck.out

。輸出共有

q 行,每行乙個整數,表示對於每一輛貨車,它的最大載重是多少。如果貨

車不能到達目的地,輸出-1。

輸入輸出樣例

輸入樣例#1:

4 31 2 4

2 3 3

3 1 1

31 3

1 41 3

輸出樣例#1:

3

-13說明

對於30%的資料,

0 < n < 1,000

,0 < m < 10,000

,0 < q< 1,000;對於

60%的資料,

0 < n < 1,000

,0 < m < 50,000

,0 < q< 1,000;對於

100%

的資料,

0 < n < 10,000

,0 < m < 50,000

,0 < q< 30,000

,0 ≤ z ≤ 100,000。

point.1

建樹

顯然給出的資料只能構造出一張無向圖,可能有重邊,可能不連通。直接從這張圖上跑無法達到我們的目的,所以要跑一遍最大生成樹,生成多棵無根樹構成森林。實現時要另開乙個鄰接表存生成的樹,雙向邊連線。另外要注意跑kruscal的時候get兩個端點的祖先時注意進行路徑壓縮,防止超時。

point.2 dfs

列舉節點,理論上同一棵樹上的每個節點都可以作為根,所以只要碰到沒有搜過的點就來一把dfs,搜過的點都打上標記,這樣可以遍歷整個森林。dfs的目的有兩個:

1.確定每一棵樹中節點的父子關係,同時維護f[i][0](從第i個節點向上跳2^0步到達的節點,實際上就是father[i])和minp[i][0](從第i個節點向上跳2^0步走過的邊中的最短邊);

2. 遍歷整棵樹,求出每個節點的深度d[i]。

point.3 rmq

、lca

的初始化

具體演算法就不囉嗦了,本質上和模板差不多,只不過這裡是樹上維護rmq,寫法上和區間rmq不太一樣(其實更好寫了)。

point.4

求lca

同時維護答案

注意目的不在找到lca,而是在找的過程中維護最小值,返回值也是這個最小值。

解題思路

都在上文裡提到了,這裡講幾個debug時碰到的蠢斃了的bug:

1. kruscal路徑壓縮時,fa[x]=get(fa[x])要放在return之前,否則會導致這一子程式變成回溯過程。結果……t了8個點夠不夠狠?

2. 最大生成樹,所以要過載 < 。還有建邊時要建雙·向·邊。

3. dfs時要先列舉而不能只從1開始搜……好吧這其實並不算bug……

4. 倍增初始化第二維最好至少要跑到15,沒錯真的有2^10+的深度……

5. 讀入一對x/y後,先判斷是否在同一棵樹上,不在直接輸出「-1」,否則跑lca。

6. 陣列要開夠要開夠要開夠……不要忘了邊數是m*2。

參考**

#include#include#include#includeusing namespace std;

int num=0, num2=0,ans,mi,n,m;

int v[10005], v2[10005] ,fa[10005],d[10005],pre_len[10005],pre_num[10005];

int minp[10005][20], f[10005][20];

bool vis[10005];

struct mc

}e[100005],p[100005];

void put(int x,int y,int l)

int get(int x)}

void put2(int x,int y,int l)

void dfs(int x,int fa,int dep)

}} void kru()

}memset(vis,0,sizeof(vis));

for(int i=1;i<=n;i++)

}} int log_(int n)

dp>>=1;}}

if(x==y) return mi;

boolff=1;

intk=log_(d[x]);

while(ff)}}

mi=min(mi,minp[x][0]);

mi=min(mi,minp[y][0]);

return(mi);}

int main()

kru();

pre();

intp,root;

scanf("%d",&p);

for(int i=1;i<=p;i++)

ans=lca(x,y);

printf("%d\n",ans);

}}

洛谷 1967 貨車運輸

在圖上從x到y找一條簡單路徑,使得路徑上最小值最大 暴力會t因為需要的是較大的那些邊,故可以求最大生成樹,然後lca陣列開小了 include include include define inf 0x3f3f3f3f define maxn 50005 using namespace std in...

洛古1967 貨車運輸

具體思路 最大生成樹 倍增lca 首先感謝tqc大佬為我的耐心修改 你可能是改了個shi 貼 using namespace std const int maxn 100005 const int maxm 100005 int n,m,head maxn father maxn top,depth...

洛谷 P1967 貨車運輸

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