Codeforces 1149D 最短路 状压DP

题意及思路:https://blog.csdn.net/yzyyylx/article/details/90145400

这题主要巧妙在分析了最短路算法的性质,得出大小小于等于3的连通块一定不会被再次访问的结论。

代码:

#include <bits/stdc++.h>
using namespace std;
bool v[80][1 << 18];
int dp[80][1 << 18];
const int maxn = 1010;
struct node {
	int dis, state, now;
	bool operator < (const node& rhs) const {
		return dis > rhs.dis;
	}
};
struct Edge {
	int v, w;
};
vector<Edge> G[maxn];
int sz[maxn], num[maxn], ans[maxn];
int A, B, n, m, tot;
void add(int x, int y, int z) {
	G[x].push_back((Edge){y, z});
	G[y].push_back((Edge){x, z});
}
priority_queue<node> q;
int f[maxn];
int get(int x) {
	if(x == f[x]) return x;
	return f[x] = get(f[x]);
}
void merge(int x, int y) {
	int x1 = get(x), y1 = get(y);
	if(x1 == y1) return;
	f[x1] = y1;
	sz[y1] += sz[x1];
}
int get_num(int x) {
	if(sz[get(x)] > 3)
		return 1 << num[get(x)];
	else
		return 0;
}
void dijkstra() {
	memset(dp, 0x3f, sizeof(dp));
	memset(ans, 0x3f, sizeof(ans));
	q.push((node){0, get_num(1), 1});
	dp[1][get_num(1)] = 0;
	while(!q.empty()) {
		node tmp = q.top();
		q.pop();
		if(v[tmp.now][tmp.state]) continue;
		v[tmp.now][tmp.state] = 1;
		ans[tmp.now] = min(ans[tmp.now], tmp.dis);
		for (auto x : G[tmp.now]) {
			if(x.w == B && get(x.v) == get(tmp.now)) continue;
			if(x.w == B && (tmp.state & get_num(x.v))!= 0) continue;
			if(x.w + tmp.dis < dp[x.v][get_num(x.v) | tmp.state]) {
				dp[x.v][get_num(x.v) | tmp.state] = x.w + tmp.dis;
				q.push((node){dp[x.v][get_num(x.v) | tmp.state], get_num(x.v) | tmp.state, x.v});
			}
		}
	}
}
int main() {
	int x, y, z;
	scanf("%d%d%d%d", &n, &m, &A, &B);
	for (int i = 1; i <= n; i++) {
		f[i] = i;
		sz[i] = 1;
	}
	for (int i = 1; i <= m; i++) {
		scanf("%d%d%d", &x, &y, &z);
		add(x, y, z);
		if(z == A) {
			merge(x, y);
		}
	}
	for (int i = 1; i <= n; i++) {
		if(i == get(i) && sz[i] > 3) {
			num[i] = tot++;
		}
	}
	dijkstra();
	for (int i = 1; i <= n; i++)
		printf("%d ", ans[i]);
}

  

posted @ 2019-05-27 20:39  维和战艇机  阅读(294)  评论(0编辑  收藏  举报