題目鏈接:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=2600
分析:左偏樹的應用,詳細的分析參考下面幾個地址,錯了20遍之後終於過了。。。。
http://www.docin.com/p-451082748.html
http://zzlqxbms.diandian.com/post/2010-06-12/15847502
關於左偏樹的概念還是看黃源河的論文吧
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define mp make_pair
#define X first
#define Y second
#define MEMSET(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef unsigned int ui;
typedef long long ll;
typedef unsigned long long ull;
typedef pair pii;
typedef vector vi;
typedef vi::iterator vi_it;
typedef map mii;
typedef priority_queue pqi;
typedef priority_queue, greater > rpqi;
typedef priority_queue pqp;
typedef priority_queue, greater > rpqp;
const int MAX_N = 100000 + 2;
vector link[MAX_N];
int dis[MAX_N];
bool vis[MAX_N];
int pre[MAX_N];
int len[MAX_N]; //to calculate lca
int child[MAX_N]; //the number of children
int ans[MAX_N]; //answer
typedef struct node
{
int key;
int dist;
int add;
int left_node;
int right_node;
node *left;
node *right;
} *pnode;
pnode pnd[MAX_N];
pnode new_node(int _key, int _left_node, int _right_node)
{
pnode p = new node();
p->key = _key;
p->dist = 0;
p->add = 0;
p->left_node = _left_node;
p->right_node = _right_node;
p->left = p->right = NULL;
return p;
}
class LeftistTree
{
public:
inline void add_key(pnode a, int v) {
a->add += v;
}
pnode merge(pnode a, pnode b) {
if (a == NULL) return b;
if (b == NULL) return a;
pass_add(a);
pass_add(b);
if (a->key > b->key) swap(a, b);
a->right = merge(a->right, b);
if (a->left == NULL || a->left->dist < a->right->dist) swap(a->left, a->right);
if (a->right == NULL) a->dist = 0;
else a->dist = a->right->dist + 1;
return a;
}
pnode del_min(pnode a) {
pnode b = a;
pass_add(a);
a = merge(a->left, a->right);
delete b;
return a;
}
inline int get_min(pnode a) {
pass_add(a);
return a->key;
}
private:
inline void pass_add(pnode a) {
if (a->add) {
if (a->left != NULL) a->left->add += a->add;
if (a->right != NULL) a->right->add += a->add;
a->key += a->add;
a->add = 0;
}
}
};
void dij()
{
rpqp q;
q.push(mp(0, 1));
while (!q.empty()) {
pii tmp = q.top();
q.pop();
int u = tmp.Y, v;
if (vis[u]) continue;
vis[u] = true;
for (vector::iterator it = link[u].begin(); it != link[u].end(); ++it) {
v = it->X;
if (!vis[v] && (dis[v] == 0 || dis[v] > dis[u] + it->Y)) {
dis[v] = dis[u] + it->Y;
len[v] = len[u] + 1;
pre[v] = u;
q.push(mp(dis[v], v));
}
}
}
}
bool lca(int u, int v, int k)
{
while (len[u] > len[v]) u = pre[u];
while (len[v] > len[u]) v = pre[v];
while (u != v) u = pre[u], v = pre[v];
while (len[u] > len[k]) u = pre[u];
return u == k;
}
int main(int argc, char *argv[])
{
// freopen("D:\\in.txt", "r", stdin);
int n, m, i;
LeftistTree lft;
cin >> n >> m;
while (m--) {
int a, b, t;
scanf("%d%d%d", &a, &b, &t);
link[a].push_back(mp(b, t));
link[b].push_back(mp(a, t));
}
dij();
for (i = 2; i <= n; ++i) {
++child[pre[i]];
pnd[i] = NULL;
}
queue q;
MEMSET(vis, 0);
vector::iterator it;
for (i = 2; i <= n; ++i) if (!child[i]) q.push(i); //leaf node
while (!q.empty()) {
int k = q.front(), l, r;
q.pop();
if (k == 1) continue;
vis[k] = true;
if (--child[pre[k]] == 0) q.push(pre[k]);
for (it = link[k].begin(); it != link[k].end(); ++it) {
if (it->X == pre[k]) continue;
if (pre[it->X] == k) { //son
if (pnd[it->X] != NULL) {
lft.add_key(pnd[it->X], it->Y);
pnd[k] = lft.merge(pnd[k], pnd[it->X]);
}
}
else {
pnd[k] = lft.merge(pnd[k], new_node(dis[it->X] + it->Y, it->X, k));
}
}
while (pnd[k] != NULL && lca(pnd[k]->left_node, pnd[k]->right_node, k)) {
pnd[k] = lft.del_min(pnd[k]);
}
ans[k] = pnd[k] == NULL ? -1 : lft.get_min(pnd[k]);
}
for (i = 2; i <= n; ++i) printf("%d\n", ans[i]);
return 0;
}