poj2404中国邮递员

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <climits>

#include <string>

#include <iostream>

#include <map>

#include <cstdlib>

#include <list>

#include <set>

#include <queue>

#include <stack>



using namespace std;

const int INF=0xfffffff;

int Map[33][33];

int degree[33];

int dp[1<<16];

int n,m;

int sum;

int Min(int a,int b)

{

    return a>b?b:a;

}

void floyd()

{

    for(int k=1;k<=n;k++)

        for(int i=1;i<=n;i++)

    for(int j=1;j<=n;j++){

        if(i!=j||j!=k||k!=i){

            Map[i][j]=Min(Map[i][j],Map[i][k]+Map[k][j]);//由于图是连同的。预处理之后 两两点之间都有边直接相连

        }

    }

}



int  dfs(int  x)

{

    //cout<<x<<endl;

   // system("pause");

    if(x==0) return 0;

    if(dp[x]) return dp[x];

    int ans=INF;

    for(int i=0;i<n-1;i++)

    if(x&(1<<i)){

        for(int j=i+1;j<n;j++)

        if(x&(1<<j)){

            int cc=dfs(x-(1<<i)-(1<<j))+Map[i+1][j+1];//度数为奇数的点互相连 最小值

          //  cout<<Map[i+1][j+1]<<endl;system("pause");

            ans=Min(ans,cc);

        }

    }

    return dp[x]=ans;

}

int main()

{

    while(~scanf("%d%d",&n,&m),n){

        sum=0;

        memset(degree,0,sizeof(degree));

        memset(dp,0,sizeof(dp));

        for(int i=1;i<=n;i++)

            for(int j=1;j<=n;j++)

                Map[i][j]=INF;

        for(int i=0;i<m;i++){

            int a;int b;int c;

            scanf("%d%d%d",&a,&b,&c);

            sum+=c; degree[a]++;degree[b]++;

            if(c<Map[a][b]) Map[a][b]=Map[b][a]=c;

        }

        int x=0;

        floyd();



        for(int i=1;i<=n;i++)

        if(degree[i]&1) x|=(1<<(i-1));

        sum+=dfs(x);

        cout<<sum<<endl;

    }

    return 0;

}

你可能感兴趣的:(poj)