牛客网 十二桥问题(状压DP)

https://ac.nowcoder.com/acm/contest/1104/B
注意到\(\text{K}\)只有\(12\),因此对起点与每个毕经边对应的点单源最短路,\(\text{DP}\)出最优解

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <numeric>
#define R(a,b,c) for(register int a = (b); a <= (c); ++a)
#define nR(a,b,c) for(register int a = (b); a >= (c); --a)
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define MP make_pair
#ifdef QWQ
#define D_e_Line printf("\n------\n")
#define D_e(x) cerr << (#x) << " " << x << endl
#define C_e(x) cout << (#x) << " " << x << endl
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#define Pause() system("pause")
#include <cassert>
#define PASS fprintf(stderr, "Passing [%s] in LINE %d\n",__FUNCTION__,__LINE__)
#else
#define D_e_Line
#define D_e(x)
#define C_e(x)
#define FileOpen()
#define FileSave()
#define Pause()
#define PASS
#endif
using namespace std;
struct FastIO {
	template<typename ATP> inline FastIO& operator >> (ATP &x) {
		x = 0; int sign = 1; char c;
		for(c = getchar(); c < '0' || c > '9'; c = getchar()) if(c == '-') sign = -1;
		while(c >= '0' && c <= '9') x = x * 10 + (c ^ '0'), c = getchar();
		if(sign == -1) x = -x;
		return *this;
	}
} io;
template<typename ATP> inline ATP Max(ATP x, ATP y) {
	return x > y ? x : y;
}
template<typename ATP> inline ATP Min(ATP x, ATP y) {
	return x < y ? x : y;
}
template<typename ATP> inline ATP Abs(ATP x) {
	return x < 0 ? -x : x;
}
#include <climits>
#include <vector>
#include <queue>
#define int long long
const int N = 5e4 + 7;
const int M = 2e5 + 7;
vector<pair<int, int>> G[N];
struct E {
	int x, y, w;
} a[N];
struct nod {
	int x, w;
	nod(int _x, int _w) : x(_x), w(_w) {}
	bool operator < (const nod &rhs) const {
		return w > rhs.w;
	}
};
int dis[N], val[N], b[N], id[N], f[31][1 << 13], d[31][31];
#undef int
int main() {
FileOpen();
#define int long long
	int n, m, K;
	io >> n >> m >> K;
	R(i,1,m){
		int u, v, w;
		io >> u >> v >> w;
		G[u].emplace_back(MP(v, w));
		G[v].emplace_back(MP(u, w));
		if(i <= K) a[i] = (E){ u, v, w};
	}
	auto Dijkstra = [&](int st) {
		memset(dis, 0x3f, (n + 3) * sizeof(int));
		priority_queue<nod> q;
		dis[st] = 0;
		q.emplace(st, 0);
		while(!q.empty()){
			auto u = q.top().x, w = q.top().w;
			q.pop();
			if(dis[u] != w) continue;
			for(auto &i : G[u]){
				int v = i.first;
				if(dis[v] > dis[u] + i.second){
					dis[v] = dis[u] + i.second;
					q.emplace(v, dis[v]);
				}
			}
		}
	};
PASS;	
	Dijkstra(1);
	memcpy(val, dis, (n + 3) * sizeof(int));
	
	int tot = K << 1;
	R(i,1,K) b[i * 2 - 1] = a[i].x, b[i << 1] = a[i].y;
	sort(b + 1, b + tot + 1);
	tot = unique(b + 1, b + tot + 1) - b - 1;
	R(i,1,tot) id[b[i]] = i;
	
	R(i,1,tot){
		Dijkstra(b[i]);
		R(j,1,tot) d[i][j] = dis[b[j]];
	}
	auto ans = LLONG_MAX;
	int maxn = (1 << K) - 1;
	R(i,1,tot){
		memset(f, 0x3f, sizeof(f)), f[i][0] = 0;
		R(s,0,maxn){
			R(j,1,tot){
				if(f[j][s] == 0x3f3f3f3f) continue;
				R(k,1,K){
					if(s >> (k - 1) & 1) continue;
					int x = id[a[k].x], y = id[a[k].y];
					f[x][s ^ (1 << (k - 1))] = Min(f[x][s ^ (1 << (k - 1))], f[j][s] + d[j][y] + a[k].w);
					f[y][s ^ (1 << (k - 1))] = Min(f[y][s ^ (1 << (k - 1))], f[j][s] + d[j][x] + a[k].w);
				}
			}
		}
		R(j,1,tot){
			ans = Min(ans, (long long)val[b[i]] + f[j][maxn] + val[b[j]]);
		}
	}
	printf("%lld", ans);
	return 0;
}
/*
3 4 2
2 3 5
2 2 10
1 2 1
3 1 4
*/
posted @ 2019-11-11 20:25  邱涵的秘密基地  阅读(144)  评论(0编辑  收藏  举报