从前有一位旅者,他想要游遍天下所有的景点。这一天他来到了一个神奇的王国:在这片土地上,有n个城市,从1到n进行编号。王国中有m条道路,第i条道路连接着两个城市ai,bi,由于年代久远,所有的道路都已经不能使用。如果要修复第i条道路,需要wi的时间。为了更好的旅行,旅者想要将某些道路修复,使得1号城市能够到达n号城市,2号城市能够到达n-1号城市…k号城市能够到达n-k+1号城市。为了满足他的要求,请问最少需要多少时间去修复道路。无解请输出-1。
k<=4, n<=10000, m<=10000, n >= 2*k, wi<= 1000, 1 <= ai, bi <= n
全排列将修建1到k城市的顺序全部弄出来,
对于每个排列,
我们依次走,每次走完以后将其最短路上的值赋为0
#include
#include
#include
#include
#include
#include
#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)
#define mt(x) memset(x, 0, sizeof(x))
#define mp(x, y) memcpy(x, y, sizeof(y))
#define lson(x) x * 2
#define rson(x) x * 2 + 1
#define inf 0x7fffffff
#define N 10005
using namespace std;
typedef long long ll;
struct Node {
int To, nxt, w;
}e[N*2];
int num[24][4], orz[4], ood[N], rrd[N], dis[N], ls[N], w[N*2], n, m, K, tot, cnt = 1, sum, ans = inf;
bool vis[N], bz[4];
queue Q;
void Addedge(int u, int v, int w) {
e[++cnt].To = v, e[cnt].w = w, e[cnt].nxt = ls[u], ls[u] = cnt;
e[++cnt].To = u, e[cnt].w = w, e[cnt].nxt = ls[v], ls[v] = cnt;
}
void dfs(int now) {
if (now == K) {
rep(i, 0, K - 1) num[tot][i] = orz[i]; tot++;
return;
}
rep(i, 1, K)
if (!bz[i]) {
bz[i] = 1, orz[now] = i;
dfs(now + 1);
bz[i] = 0, orz[now] = 0;
}
}
void spfa(int x) {
while (Q.size()) Q.pop();
rep(i, 1, n) dis[i] = inf, ood[i] = 0, rrd[i] = 0;
dis[x] = 0; vis[x] = 1;
Q.push(x);
while (Q.size()) {
int u = Q.front(); Q.pop();
for (int i = ls[u]; i; i = e[i].nxt)
if (dis[e[i].To] > dis[u] + e[i].w) {
dis[e[i].To] = dis[u] + e[i].w;
ood[e[i].To] = i;
rrd[e[i].To] = u;
if (!vis[e[i].To])
vis[e[i].To] = 1, Q.push(e[i].To);
}
vis[u] = 0;
}
if (dis[n - x + 1] == inf) {
printf("-1\n"); exit(0);
}
sum += dis[n - x + 1];
int eed = n - x + 1;
for (; eed != x; eed = rrd[eed]) {
e[ood[eed]].w = 0;
e[ood[eed]^1].w = 0;
}
}
int main() {
scanf("%d %d %d", &n, &m, &K);
int x, y, z;
rep(i, 1, m) {
scanf("%d %d %d", &x, &y, &z);
Addedge(x, y, z);
}
rep(i, 1, cnt) w[i] = e[i].w;
dfs(0);
rep(i, 0, tot - 1) {
rep(j, 1, cnt) e[j].w = w[j];
sum = 0;
rep(j, 0, K - 1) spfa(num[i][j]);
ans = min(ans, sum);
}
printf("%d\n", ans);
return 0;
}