https://www.luogu.org/problemnew/show/3959
转载了【http://blog.csdn.net/KsCla/article/details/78554935】
这个思想真的是简单;
做完之后感觉自己是智障;
你看我们他妈是不是要记录2个信息
一个是当前联通块;
一个是当前联通块点的深度;
如果我们dp我们就要处理这2个东西;
那么我们记录当前联通块,然后移每一层为单位dp就可以了;
这个大佬讲的真的非常好;
而且还有一些关于二进制的骚操作;
唉,学识尚浅,智力偏低;
#include<bits/stdc++.h>
#define U(x,y) ((x-1)*(K+1)+y)
using namespace std;
inline int RR(){int v=0,k=1;char c=0;while('0'>c||c>'9'){if(c=='-')k=-1;c=getchar();}while('0'<=c&&c<='9')v=(v<<3)+(v<<1)+c-48,c=getchar();return v*k;}
inline void W(int x){if(x<0)putchar('-'),x=-x;if(x>9)W(x/10);putchar(x%10+48);}
inline void WW(int x){W(x);puts("");}
inline void read(int &x,int &y){x=RR();y=RR();}
const int N=13,M=4100;
int t[N][M],g[M][M],f[N][M],a[N][N];
int n,m,x,y,z,K,ans;
void make(){
for(int i=0;i<=K;i++)
for(int j=1;j<=n;j++){
t[j][i]=f[j][i]=1e6;
for(int k=1;k<=n;k++)
if((i&(1<<(k-1))))t[j][i]=min(t[j][i],a[k][j]);
}
for(int i=0;i<=K;i++)
for(int j=0;j<=K;j++)
g[i][j]=1e6;
for(int i=1;i<=K;i++){
int j=i&(i-1);
while(j){
g[j][i]=0;
for(int k=1;k<=n;k++)
if((i&(1<<(k-1))))g[j][i]+=t[k][j];
j=i&(j-1);
}
}
}
int main()
{
read(n,m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
a[i][j]=1e6;
for(int i=1;i<=n;i++)a[i][i]=0;
while(m--){
read(x,y);z=RR();
a[x][y]=min(a[x][y],z);
a[y][x]=a[x][y];
}
K=(1<<n)-1;
make();
for(int i=1;i<=n;i++)f[1][(1<<(i-1))]=0;
for(int i=2;i<=n;i++)
for(int j=1;j<=K;j++){
int s=j&(j-1);
while(s){
f[i][j]=min(f[i][j],f[i-1][s]+g[s][j]*(i-1));
s=j&(s-1);
}
}
ans=1e6;
for(int i=1;i<=n;i++)ans=min(ans,f[i][K]);
WW(ans);
}
然后给你们看看xjb的力量;
讲道理我noip的时候真的是好像没学过oi一样
https://www.luogu.org/record/show?rid=4731812
唉,人菜则颓,人颓则菜;