題目大意:給定乙個 n 個點,m 條邊的無向圖,邊有兩個邊權 a, b,求從 1 號節點到 n 號節點路徑的兩個權值和的最大值最小是多少。
題解:對於有兩個屬性的結構的最優化問題,可以考慮先按照其中乙個分量進行排序。接著從小到大列舉這個有序的分量,計算以當前列舉到的值為這一分量的最大值時,全域性的最優解是多少。因此,需要高效維護的是如何求出另乙個分量的最優解。
對於這道題來說,考慮對 a 分量進行排序,並按從小到大的順序依次加邊。對於即將加入的第 i 條邊來說,若加入這條邊使得兩個本來不聯通的點聯通,則直接加入;若加入這條邊之後,形成了環,則比較加入這條邊 b 的權值和這條邊兩個端點之間路徑上 b 的最大值,若當前邊的 b 更小,則斷開路徑上最大邊權的邊,並加入當前這條邊即可。利用 lct 進行維護 b 即可。
**如下
#include using namespace std;
struct edge
};struct node
void unsafe_reverse()
void pull()
if (r != null)
} void push()
if (r != null)
rev = 0;
} }};bool is_root(node* v)
return (v->p == null) || (v->p->l != v && v->p->r != v);
}void rotate(node* v)
if (v->p->r == u)
} if (v == u->l)
if (v == u->r)
u->pull();
v->pull();
}void deal_with_push(node* v)
v = v->p;
} while (!s.empty())
}void splay(node* v) else
} rotate(v); }}
void access(node* v)
}void make_root(node* v)
node* find_root(node* v)
splay(v);
return v;
}void link(node* v, node* u)
}void cut(node* v, node* u)
}void split(node* v, node* u)
node* find(node* v, int b)
if (v->l != null && v->l->maxb == b) else
} return v;
}int main()
sort(e.begin(), e.end(), [&](const edge &x, const edge &y) );
vectort(n + m);
for (int i = 0; i < n; i++)
int ans = 1e9;
for (int i = 0; i < m; i++) else
} if (find_root(t[0]) == find_root(t[n - 1]))
} if (ans == 1e9) else
return 0;
}
洛谷 P2387 魔法森林
題目描述 為了得到書法大家的真傳,小 e 同學下定決心去拜訪住在魔法森林中的隱 士。魔法森林可以被看成乙個包含 n 個節點 m 條邊的無向圖,節點標號為 1,2,3,n,邊標號為 1,2,3,m。初始時小 e 同學在 1 號節點,隱士則住在 n 號節點。小 e 需要通過這一片魔法森林,才能夠拜訪到隱...
洛谷 P2387 魔法森林
為了得到書法大家的真傳,小 e 同學下定決心去拜訪住在魔法森林中的隱 士。魔法森林可以被看成乙個包含 n 個節點 m 條邊的無向圖,節點標號為 1,2,3,n,邊標號為 1,2,3,m。初始時小 e 同學在 1 號節點,隱士則住在 n 號節點。小 e 需要通過這一片魔法森林,才能夠拜訪到隱士。魔法森...
洛谷P2387 魔法森林 spfa
為了得到書法大家的真傳,小 e 同學下定決心去拜訪住在魔法森林中的隱 士。魔法森林可以被看成乙個包含 n 個節點 m 條邊的無向圖,節點標號為 1,2,3,n,邊標號為 1,2,3,m。初始時小 e 同學在 1 號節點,隱士則住在 n 號節點。小 e 需要通過這一片魔法森林,才能夠拜訪到隱士。魔法森...