大致意思是,给你一些点,一些边,让你求从1点出发,最后又回到1点的最小代价,每条边都进过至少一次
应该很容易联想到欧拉回路吧,欧拉回路的充要条件就是所有点度为偶数。所以这道题,我们只需对度为奇数的点之间,连一条“边”,是他变成偶数度的点即可
这条“边”是由现存的边构成的,长度可以跑floyd算出
然后,需要注意的是,如何判定无答案,这个要仔细想想。。。。我就在这里wa了无数发。。、、
#include<iostream>
#include<cstdio>
#include<math.h>
#include<algorithm>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<queue>
#include<string.h>
#include<cstring>
#include<vector>
#include<time.h>
#include<stdlib.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef pair<int,int> PII;
#define INFLL 0x3f3f3f3f3f3f3f3f
#define FIN freopen("input.txt","r",stdin)
#define mem(x,y) memset(x,y,sizeof(x))
typedef unsigned long long ULL;
typedef long long LL;
const int MX=22;
int G[MX][MX];
int cnt[MX];
int bin[MX];
int cntbin[MX];
int n,m;
int _find(int x)
{
return x==bin[x]?x:bin[x]=_find(bin[x]);
}
int vis [MX];
int dfs()
{
int k,minn=INF;;
int i=1;
for(; i<=n; i++) if((cnt[i]&1)&&vis[i]==0) break;
vis[i]=1;
for(int j=i+1; j<=n; j++)
if((cnt[j]&1)&&vis[j]==0)
{
vis[j]=1;
minn=min(minn,dfs()+G[i][j]);
vis[j]=0;
}
vis[i]=0;
if(minn==INF)minn=0;
return minn;
}
int main()
{
freopen("input.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
for(int i=1; i<=n; i++) bin[i]=i;
mem(cnt,0);
mem(cntbin,0);
mem(G,0x3f);
int ans=0;
for(int i=1; i<=m; i++)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
cnt[x]++;
cnt[y]++;
ans+=w;
G[x][y]=G[y][x]=min(G[x][y],w);
int fa=_find(x),fb=_find(y);
cntbin[fa]++;
cntbin[fb]++;
if(fa!=fb)
{
bin[fa]=fb;
cntbin[fb]+=cntbin[fa];
}
}
if(cntbin[_find(1)]!=2*m)puts("-1");
else
{
for(int k=1; k<=n; k++)
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++) G[i][j]=min(G[i][j],G[i][k]+G[k][j]);
mem(vis,0);
printf("%d\n",ans+dfs());
}
}
return 0;
}