为什么没写个Floyd写个Spfa。。。。
度为奇数的点两两匹配,这样所有的点的度数就都为偶数了,
然后就是欧拉回路了,
然后求个最优匹配
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int N=20;
const int M=2000+10;
const int inf=0x3f3f3f3f;
typedef __int64 LL;
struct Edge {
int v,next,w;
Edge(int v=-1,int next=-1,int w=-1):v(v),next(next),w(w){}
}e[M*2];
int head[N],total;
void adde(int u,int v,int w){
e[total]=Edge(v,head[u],w);head[u]=total++;
}
void init(){
memset(head,-1,sizeof(head));total=0;
}
int vis[N],dis[N];
queue<int> qq;
void spfa(int s){
memset(vis,0,sizeof(vis));memset(dis,0x3f,sizeof(dis));
dis[s]=0;vis[s]=1;
qq.push(s);
while(!qq.empty()){
int u=qq.front();qq.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
if(!vis[v]){
vis[v]=1;qq.push(v);
}
}
}
}
}
int du[N];
int sta[N*N],top,ans[N*N];
int mp[N][N];
int f[N];
int Find(int x){
if(x==f[x])return x;
return f[x]=Find(f[x]);
}
int dp[1<<20];
int aa[M],bb[M];
int main(){
#ifdef DouBi
freopen("in.cpp","r",stdin);
#endif // DouBi
int n,m;while(scanf("%d%d",&n,&m)!=EOF){
init();
int sum=0;
memset(du,0,sizeof(du));
for(int i=1;i<=n;i++)f[i]=i;
for(int i=0;i<m;i++){
int a,b,c;scanf("%d%d%d",&a,&b,&c);
aa[i]=a,bb[i]=b;
sum+=c;
du[a]++;du[b]++;
adde(a,b,c);adde(b,a,c);
f[Find(a)]=Find(b);
}
int cnt=0;
for(int i=0;i<m;i++){
if(Find(aa[i])!=Find(1))cnt++;
}
if(cnt){
printf("-1\n");continue;
}
top=0;
for(int i=1;i<=n;i++){
if(du[i]%2==1){
sta[top++]=i;
}
}
for(int i=0;i<top;i++){
spfa(sta[i]);
for(int j=0;j<top;j++){
mp[i][j]=dis[sta[j]];
}
}
// for(int i=0;i<top;i++)printf("%d ",sta[i]);printf("\n");
// for(int i=0;i<top;i++){
// for(int j=0;j<top;j++)printf("%d ",mp[i][j]);printf("\n");
// }
n=top;top=0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
sta[top]=(1<<i)|(1<<j);
ans[top++]=mp[i][j];
}
}
dp[0]=0;
for(int i=1;i<(1<<n);i++){
dp[i]=inf;
for(int j=0;j<top;j++){
if((i&sta[j])==sta[j]){
dp[i]=min(dp[i^sta[j]]+ans[j],dp[i]);
}
}
//printf("%d %d\n",i,dp[i]);
}
printf("%d\n",dp[(1<<n)-1]+sum);
}
return 0;
}