updata 1.22:附上樹鏈剖分的**,
前置知識 :
思路:
觀察題目,發現司機們並不管送貨路程的遠近,只管能裝貨物的總數。如果有一條比較遠的路,但能裝貨物的總量更大,司機還是會繞道走的。由此來看,一些較小的邊是不會被走到的(除了沒有其他路可走),於是我們只需要在保證在沒有破壞圖的連通性的條件下(但題目沒說圖一開始就是連通的)刪掉較小的邊。完成以上操作,我們只需先建立乙個最大生成樹即可(注意先把圖的資料存起來,然後邊跑 $kruskal$ 邊將確定的邊再連上),其實也是方便完成 $step2$ 的操作罷了。
操作方式 :處理最大生成樹的方法和處理最小生成樹的方法等同(千萬不要把 $cmp$ 裡的大於號小於號給寫反了),只不過要在 $kruskal$ 中把已經確定的邊連上,$warning$ —— 是雙向邊。
處理完了圖的操作後,我們思考如何將司機所能運輸的最大載貨量給求出來,同時,看資料,加上外層的一層迴圈,只能用 $log(n)$ 的複雜度求出路徑上的距離, $lca$ 恰恰是如此。在處理點深度和父節點時,可以像 $fa[u][i]$ 一樣建立乙個 $q[u][i]$ ,表示從$u$到$u$的第 $2$i 個祖先上的路徑的最小邊權是多少(但這裡邊權存在深度較深的那個節點上面了)。然後邊跑 $lca$ 在起點和終點向上「跳」時進行更新 $ans$,及 $ans$ $=$ $min(ans$, $min(q[x][i]$, $q[y][i]))$,還有在 $x$,$y$中較深的節點向上「跳」時,也需要更新 $ans$,及 $ans$ $=$ $min(ans$, $q[u][i])$。當然,在初始化深度和 $fa$ 陣列的時候,也需要處理一下 $q$ 陣列的初始化,及 $q[u][i]$ $=$ $min(q[u][i$ $-$ $1]$, $q[fa[u][i$ $-$ $1]][i$ $-$ $1])$。然後,就只需要邊跑 $lca$ 邊更新答案就好了。
操作方式 :正常 $lca$ $+$ 更新 $q$ 陣列與 $ans$。
1 #include 2#define inf 0x3f3f3f3f
3using
namespace
std;
4int n, m, p, head[1000001], num, depth[1000001], fa[1000001][21], q[1000001][21], fa[1000001], size[1000001];//
size陣列是按秩合併裡需要的,可以不管
5struct
node
6stu[2000001];9
struct
node
10tree[2000001];//
kruskal裡需要用到的陣列
13 inline int
cmp(node a, node b)
1417 inline void add(int x, int y, int z)//
加邊 18
25 inline int find(int x)//
查詢 26
29 inline void unity(int x, int y)//
按秩合併
3038
else
3943
return;44
}45 inline void kruskal()//
最大生成樹
4661}62
}63return;64
}65 inline void dfs(int u, int father, int value)//
value是邊權,存在深度深的節點上面
6676
for(register int i = head[u]; i; i =stu[i].next)
7783}84
return;85
}86 inline void up(int &u, int step, int &ans)//
將深度跳到相同位置
8796}97
return;98
}99 inline int lca(int x, int y)//
lca
100105
int ans =inf;
106if(depth[x] 107110 up(x, depth[x] -depth[y], ans);
111if(x ==y)
112115
int maxn = ceil(log(depth[x]) / log(2
));116
for(register int i = maxn; i >= 0; --i)
117124
}125
return min(ans, min(q[x][0], q[y][0]));//
最後父節點別忘了
126}
127signed main()
128135
for(register int i = 1, x, y, z; i <= m; ++i)
136139
kruskal();
140for(register int i = 1; i <= n; ++i)//
注意該圖可能不連通,於是需要多次dfs初始化
141146
}147 scanf("
%d", &p);
148for(register int i = 1, x, y; i <= p; ++i)
149153
return0;
154 }
洛谷 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...