TOJ 2600 Safe Travel -- 左偏樹

題目鏈接: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;
}

發佈了49 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章