# BZOJ4006 JLOI2015 管道连接(斯坦纳树生成森林)

4006: [JLOI2015]管道连接

Time Limit: 30 Sec  Memory Limit: 128 MB

Description

Input

Output

Sample Input
5 8 4
1 2 3
1 3 2
1 5 1
2 4 2
2 5 1
3 4 3
3 5 1
4 5 1
1 1
1 2
2 3
2 4

Sample Output
4

HINT

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>

using namespace std;
const int N = 1000 + 5;
const int inf = 0xf0f0f0f;

int n, m, p, cnt, channel, tot_channel;
int g[1025], f[N][1025], head[N], inque[N];
queue <int> q;

struct Edge {
int from, to, dis, next;
}edges[6005];

struct Data {
int c, num;
bool operator < (const Data &STD) const {
return c < STD.c;
}
}key[11];

void insert(int from, int to, int dis) {
++ cnt;
edges[cnt].from = from; edges[cnt].to = to; edges[cnt].dis = dis;
edges[cnt].next = head[from]; head[from] = cnt;
}

void spfa(int State) {
while(!q.empty()) {
int x = q.front(); q.pop();
inque[x] = 0;
for(int i = head[x]; i; i = edges[i].next) {
int v = edges[i].to;
if(f[v][State] > f[x][State] + edges[i].dis) {
f[v][State] = f[x][State] + edges[i].dis;
if(!inque[v]) {
inque[v] = 1;
q.push(v);
}
}
}
}
}

int solve() {
int U = 1 << channel;
for(int State = 0; State < U; ++ State) {
for(int i = 1; i <= n; ++ i) {
for(int s = (State - 1) & State; s; s = (s - 1) & State)
f[i][State] = min(f[i][State], f[i][s] + f[i][State - s]);
if(f[i][State] != inf) q.push(i), inque[i] = 1;
}
spfa(State);
}
int ans = inf;
for(int i = 1; i <= n; ++ i) ans = min(ans, f[i][U - 1]);
return ans;
}

#define stone_
int main() {
#ifndef stone_
freopen("channel.in", "r", stdin);
freopen("channel.out", "w", stdout);
#endif

int u, v, w;
scanf("%d%d%d", &n, &m, &p);
for(int i = 1; i <= m; ++ i) {
scanf("%d%d%d", &u, &v, &w);
insert(u, v, w); insert(v, u, w);
}
for(int i = 1; i <= p; ++ i)
scanf("%d%d", &key[i].c, &key[i].num);
sort(key + 1, key + p + 1);
for(int i = 1; i <= p; ++ i) {
if(key[i].c != key[i - 1].c) ++ tot_channel;
key[i].c = tot_channel;
}
int U = 1 << tot_channel;
memset(g, 0xf, sizeof g);
for(int State = 0; State < U; ++ State) {
memset(f, 0xf, sizeof f);
channel = 0;
for(int i = 1; i <= p; ++ i)
if(State & 1 << (key[i].c - 1)) {
f[key[i].num][1 << channel] = 0;
channel ++;
}
g[State] = solve();
}
for(int State = 0; State < U; ++ State) {
for(int s = (State - 1) & State; s; s = (s - 1) & State)
g[State] = min(g[State], g[s] + g[State - s]);
}
printf("%d\n", g[U - 1]);

#ifndef stone_
fclose(stdin); fclose(stdout);
#endif
return 0;
}

posted @ 2016-04-19 11:28  漫步者。！~  阅读(102)  评论(0编辑  收藏