Codeforces 464E The Classic Problem (线段树+哈希)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <ctime>
#include <functional>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;


#define eps 1e-10
#define N 102000
#define B 1000007
#define M 3000020
#define inf 0x3f3f3f3f
#define LL long long
#define pii pair<int, int>
#define MP make_pair
#define fi first
#define se second
#define md (ll + rr >> 1)
#define ls (i << 1)
#define rs (ls | 1)
#define md (ll + rr >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs

const int m1 = 1000000007;
const int m2 = 1000000002;
const int b = 2;

int ch[N * 200][2], cnt[N * 200];
LL hx[N * 200];
int tot;
int p1[N], p2[N];


int fst[N], nxt[M], vv[M], cost[M], e;


int n, m;
int s, t;
int pre[N], rt[N];
bool inq[N];
int ans;

void init() {
	memset(fst, -1, sizeof fst);
	e = 0;
	p1[0] = p2[0] = 1;
	for(int i = 1; i < N; ++i) {
		p1[i] = 1LL * p1[i - 1] * b % m1;
		p2[i] = 1LL * p2[i - 1] * b % m2;
	}
}

void add(int u, int v, int c) {
	cost[e] = c, vv[e] = v, nxt[e] = fst[u], fst[u] = e++;
}

void push_up(int k, int ll, int rr) {
	cnt[k] = cnt[ch[k][0]] + cnt[ch[k][1]];
	LL x = hx[ch[k][0]] >> 32;
	LL y = hx[ch[k][0]] & ((1LL << 32) - 1);
	LL xx = hx[ch[k][1]] >> 32;
	LL yy = hx[ch[k][1]] & ((1LL << 32) - 1);
	x = (x * p1[rr - md] + xx) % m1;
	y = (y * p2[rr - md] + yy) % m2;
	hx[k] = (x << 32) + y;
}


int update(int i, int x, int v, int ll, int rr) {
	int k = ++tot;
	ch[k][0] = ch[i][0];
	ch[k][1] = ch[i][1];
	cnt[k] = cnt[i] + v;
	if(ll == rr) {
		hx[k] = ((1LL * v) << 32) + v;
		return k;
	}
	if(x <= md) ch[k][0] = update(ch[i][0], x, v, ll, md);
	else ch[k][1] = update(ch[i][1], x, v, md + 1, rr);
	push_up(k, ll, rr);
	return k;
}


int query(int i, int x, int ll, int rr) {
	if(cnt[i] == rr - ll + 1) return -1;
	if(ll == rr) {
		if(cnt[i] == 1) return -1;
		return ll;
	}
	if(x > md) return query(ch[i][1], x, md + 1, rr);
	if(x == ll) {
		if(cnt[ch[i][0]] == md - ll + 1) return query(ch[i][1], md + 1, md + 1, rr);
		return query(ch[i][0], x, ll, md);
	}
	int t = query(ch[i][0], x, ll, md);
	if(t != -1) return t;
	return query(ch[i][1], md + 1, md + 1, rr);
}

int clear0(int i, int l, int r, int ll, int rr) {
	if(ll == l && rr == r) {
		return 0;
	}
	int k = ++tot;
	ch[k][0] = ch[i][0];
	ch[k][1] = ch[i][1];
	if(r <= md) ch[k][0] = clear0(ch[i][0], l, r, ll, md);
	else if(l > md) ch[k][1] = clear0(ch[i][1], l, r, md + 1, rr); 
	else {
		ch[k][0] = clear0(ch[i][0], l, md, ll, md);
		ch[k][1] = clear0(ch[i][1], md + 1, r, md + 1, rr);
	}
	push_up(k, ll, rr);
	return k;
}


bool cmp(int u, int v, int ll, int rr) {
	if(hx[u] == hx[v]) return 0;
	if(ll == rr) {
		return cnt[u] < cnt[v];
	}
	if(hx[ch[u][1]] != hx[ch[v][1]]) return cmp(ch[u][1], ch[v][1], md + 1, rr);
	return cmp(ch[u][0], ch[v][0], ll, md);
}
void dfs(int u, int ll, int rr) {
	if(ll == rr) {
		if(cnt[u]) ans = ans * 2 + 1;
		else ans *= 2;
		ans %= m1;
		return;
	}
	dfs(ch[u][1], md + 1, rr);
	dfs(ch[u][0], ll, md);
}

struct node {
	int x, d;
	node() {}
	node(int x, int d):x(x), d(d) {}
	bool operator < (const node &b) const {
		return cmp(b.d, d, 0, N - 1);
	}
};
void spfa() {
	priority_queue<node> q;
	q.push(node(s, rt[s]));
	for(int i = 1; i <= n; ++i) if(i != s) rt[i] = update(0, N - 1, 1, 0, N - 1);
	while(!q.empty()) {
		int u = q.top().x;
		int d = q.top().d;
		q.pop();
		if(rt[u] != d) continue;
		
		for(int i = fst[u]; ~i; i = nxt[i]) {
			int v = vv[i], c = cost[i];
			int p = query(rt[u], c, 0, N - 1);
			if(p == -1) {
				vector<int> g1;
				g1[1] = -1;
			}
			int t = rt[u];
			if(p > c) t = clear0(t, c, p - 1, 0, N - 1);
			t = update(t, p, 1, 0, N - 1);
			if(cmp(t, rt[v], 0, N - 1)) {
				rt[v] = t;
				pre[v] = u;
				q.push(node(v, rt[v]));
			}
		}
	}
}
			


int main() {
	scanf("%d%d", &n, &m);
	init();
	for(int i = 1; i <= m; ++i) {
		int u, v, c;
		scanf("%d%d%d", &u, &v, &c);
		add(u, v, c);
		add(v, u, c);
	}
	scanf("%d%d", &s, &t);
	if(s == t) {
		printf("0\n1\n1\n");
		return 0;
	}

	spfa();
	if(pre[t] == 0) {
		puts("-1");
		return 0;
	}
	dfs(rt[t], 0, N - 1);
	printf("%d\n", ans);
	vector<int> vt; vt.push_back(t);
	while(t != s) {
		t = pre[t];
		vt.push_back(t);
	}
	reverse(vt.begin(), vt.end());
	printf("%d\n", (int)vt.size());
	for(int i = 0; i < vt.size(); ++i) {
		printf("%d%c", vt[i], i == vt.size() - 1? '\n': ' ');
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值