明显是一道斯坦纳树的题。

然而这题只需要属性相同的点互相连接。

我们还是照常先套路求出\(ans[s]\)。

然后对\(ans[s]\)做子集DP即可。

具体看代码。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
const int INF=1e9;
const int N=1111;
const int M=3333;
struct edge{
int to,nxt,w;
}e[M*2];
int cnt,head[N];
void add_edge(int u,int v,int w){
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
e[cnt].w=w;
head[u]=cnt;
}
struct node{
int id,w;
node(int idd=0,int ww=0){
id=idd,w=ww;
}
};
struct point{
int k,id;
}c[N];
bool operator <(node a,node b){
return a.w>b.w;
}
priority_queue<node> q;
bool vis[N];
int dp[N][N];
void dij(int x){
memset(vis,0,sizeof(vis));
while(!q.empty()){
node uu=q.top();
q.pop();
int u=uu.id;
if(vis[u])continue;vis[u]=1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(dp[x][v]>dp[x][u]+e[i].w){
dp[x][v]=dp[x][u]+e[i].w;
q.push(node(v,dp[x][v]));
}
}
}
}
int a[15],num[15];
int n,m,k,tot,ans[N];
bool check(int s){
for (int i=1;i<=k;++i) a[i]=0;
for (int i=1;i<=k;++i)
if (s&(1<<(i-1))) a[c[i].k]++;
for (int i=1;i<=k;++i) if (a[i]&&a[i]!=num[i]) return false;
return true;
}
int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return sum*f;
}
int main(){
n=read(),m=read(),k=read();
for(int i=1;i<=m;i++){
int u=read(),v=read(),w=read();
add_edge(u,v,w);add_edge(v,u,w);
}
tot=(1<<k)-1;
for(int i=0;i<=tot;i++)
for(int j=1;j<=n;j++)
dp[i][j]=INF;
for(int i=1;i<=k;i++){
c[i].k=read(),c[i].id=read();
num[c[i].k]++;
}
for(int i=1;i<=k;i++)dp[1<<i-1][c[i].id]=0;
for(int t=0;t<=tot;t++){
for(int i=1;i<=n;i++)
for(int j=t;j;j=(j-1)&t)
dp[t][i]=min(dp[t][i],dp[j][i]+dp[t^j][i]);
for(int i=1;i<=n;i++)if(dp[t][i]!=INF)q.push(node(i,dp[t][i]));
dij(t);
}
for(int i=0;i<=tot;i++){
ans[i]=INF;
for(int j=1;j<=n;j++)
ans[i]=min(ans[i],dp[i][j]);
}
for(int i=0;i<=tot;i++)
if(check(i))
for(int j=i;j;j=(j-1)&i)
if(check(j))
ans[i]=min(ans[i],ans[j]+ans[j^i]);
printf("%d",ans[tot]);
return 0;
}

最新文章

  1. FreeCAD鼠标操作指南
  2. Jfinal连接SQLSERVER相关配置说明
  3. 详细讲解nodejs中使用socket的私聊的方式
  4. nginx服务器设置url的优雅链接
  5. RESTClient - firefox插件
  6. Linq 查询基本操作
  7. Linux学习之chkconfig命令
  8. 使用(Unicode字符)让inline水平元素换行
  9. Leetcode 136.只出现一次的数字 By Python
  10. python3 模拟鼠标和键盘操作
  11. PNP的学习-P3P
  12. 高阶组件 HOC
  13. Tree Recovery
  14. python 用type()创建类
  15. FreeSWITCH增加iLBC编码
  16. Windows Azure Mobiles Services实现client的登录注冊
  17. python--生成器,生成器推导式, yield from
  18. jPage.js分页
  19. JavaScript中label与break配合使用
  20. juniper设置共享上网(注意事项)

热门文章

  1. vncserve安装与使用
  2. 搞定PHP面试 - 变量知识点整理
  3. Jenkins持续构建打包后端服务流程详解
  4. M​a​y​a​ ​2​0​1​2​ ​破​解​安​装​全​图​文​教​程
  5. 屌丝、小白怎么拿国内巨头offer
  6. Struts2概述及与Struts1的对照
  7. hdu 3697 Selecting courses (暴力+贪心)
  8. C4
  9. 避免ANR异常
  10. checkbox改写