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 國有 ...