# 【bzoj4006】[JLOI2015]管道连接 斯坦纳树+状压dp

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

4

#include <queue>
#include <cstdio>
#include <cstring>
#include <utility>
using namespace std;
typedef pair<int , int> pr;
priority_queue<pr> q;
int head[1010] , to[6010] , len[6010] , next[6010] , cnt , c[15] , d[15] , f[1030][1010] , vis[1030][1010] , g[1030];
inline void add(int x , int y , int z)
{
to[++cnt] = y , len[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
}
int main()
{
int n , m , p , i , j , k , x , y , z;
scanf("%d%d%d" , &n , &m , &p);
memset(f , 0x3f , sizeof(f));
for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%d" , &x , &y , &z) , add(x , y , z) , add(y , x , z);
for(i = 1 ; i <= p ; i ++ ) scanf("%d%d" , &c[i] , &d[i]) , f[1 << (i - 1)][d[i]] = 0;
for(i = 1 ; i <= n ; i ++ ) f[0][i] = 0;
for(i = 1 ; i < 1 << p ; i ++ )
{
for(j = i ; j ; j = i & (j - 1))
for(k = 1 ; k <= n ; k ++ )
f[i][k] = min(f[i][k] , f[j][k] + f[i ^ j][k]);
for(j = 1 ; j <= n ; j ++ ) q.push(pr(-f[i][j] , j));
while(!q.empty())
{
x = q.top().second , q.pop();
if(vis[i][x]) continue;
vis[i][x] = 1;
for(j = head[x] ; j ; j = next[j])
if(f[i][to[j]] > f[i][x] + len[j])
f[i][to[j]] = f[i][x] + len[j] , q.push(pr(-f[i][to[j]] , to[j]));
}
}
memset(g , 0x3f , sizeof(g));
for(i = 1 ; i < 1 << p ; i ++ )
{
k = 0;
for(j = 1 ; j <= p ; j ++ )
if(i & (1 << (c[j] - 1)))
k |= (1 << (j - 1));
for(j = 1 ; j <= n ; j ++ ) g[i] = min(g[i] , f[k][j]);
for(j = i ; j ; j = i & (j - 1)) g[i] = min(g[i] , g[j] + g[i ^ j]);
}
printf("%d\n" , g[(1 << p) - 1]);
return 0;
}


posted @ 2017-12-20 20:57  GXZlegend  阅读(298)  评论(0编辑  收藏