斯坦纳树似乎是带有关键点的最小生成树
暴力状压,然后还有染色,似乎要再套一个状压
#include<set>
#include<map>
#include<ctime>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define T 3333
#define MX 1000000000
using namespace std;
int sc()
{
int i=0; char c=getchar();
while(c>'9'||c<'0')c=getchar();
while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
return i;
}
int head[T],nxt[T*3],lst[T*3],v[T*3];
int f[T][T/3],vis[T],st[11];
int n,m,p,P,tot,S;
int g[66];
vector<int> a[11],col[11],b;
queue<int> q;
void insert(int x,int y,int z)
{
lst[++tot]=y; nxt[tot]=head[x]; v[tot]=z; head[x]=tot;
lst[++tot]=x; nxt[tot]=head[y]; v[tot]=z; head[y]=tot;
}
void Pretreatment(int p)
{
for(int i=1;i<=n;i++)
for(int j=0;j<p;j++)
f[i][j]=MX;
}
void spfa(int k)
{
while(!q.empty())
{
int x=q.front();q.pop();vis[x]=0;
for(int i=head[x];i;i=nxt[i])
{
if(f[lst[i]][k]>f[x][k]+v[i])
{
f[lst[i]][k]=f[x][k]+v[i];
if(!vis[lst[i]])q.push(lst[i]),vis[lst[i]]=1;
}
}
}
}
int Steiner_tree(int K)
{
for(int i=1;i<K;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=i&(i-1);k;k=i&(k-1))
f[j][i]=min(f[j][i],f[j][k]+f[j][i-k]);
if(f[j][i]!=MX) q.push(j),vis[j]=1;
}
spfa(i);
}
int ans=MX;
for(int i=1;i<=n;i++)
ans=min(ans,f[i][K-1]);
return ans;
}
int main()
{
n=sc(),m=sc(),p=sc();
for(int i=1;i<=m;i++)
{
int x=sc(),y=sc(),z=sc();
insert(x,y,z);
}
for(int i=1;i<=p;i++)
{
int x=sc(),y=sc();
a[x].push_back(y);
}
for(int i=1;i<=p;i++)
{
if(a[i].size()>1)
{
S++;
for(int j=0;j<a[i].size();j++)
{
col[S].push_back(a[i][j]);
}
}
}
for(int i=1;i<(1<<S);i++) g[i]=MX;
for(int i=1;i<(1<<S);i++)
{
int p=0; b.resize(0);
for(int j=1;j<=S;j++)
if(i&(1<<j-1))
{
for(int k=0;k<col[j].size();k++)
{
b.push_back(col[j][k]);
p++;
}
}
Pretreatment(1<<p);
for(int j=0;j<b.size();j++) f[b[j]][1<<j]=0;
g[i]=Steiner_tree(1<<p);
}
for(int i=1;i<(1<<S);i++)
{
for(int k=i&(i-1);k;k=i&(k-1))
g[i]=min(g[i],g[k]+g[i-k]);
}
cout<<g[(1<<S)-1];
return 0;
}