此题和 hdu 3691 Nubulsa Expo 几乎一样
不再解释
代码:
#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

const int INF=0x7fffffff;
const int N=505;
int a[N][N];
int dist[N];
bool visited[N],dele[N];
int n,m;
int nd1,nd2;
void Prim()
{
    int st=1;
    while(dele[st])
    ++st;
    memset(dist,0,sizeof(dist));
    for(int i=1;i<=n;++i)
    {
        if(!dele[i])
        {
            dist[i]=a[st][i];
        }
    }
    nd1=nd2=st;
    memset(visited,false,sizeof(visited));
    visited[st]=true;
    for(int w=1;w<n;++w)
    {
        int M=0,k=0;
        for(int i=1;i<=n;++i)
        {
            if(!dele[i]&&!visited[i]&&dist[i]>M)
            {
                M=dist[i];k=i;
            }
        }
        if(k==0)
        break;
        visited[k]=true;
        for(int i=1;i<=n;++i)
        {
            if(!dele[i]&&!visited[i])
            {
                dist[i]+=a[k][i];//这里好奇怪
            }
        }
        nd2=nd1;//最后更新点 和倒数第二更新点
        nd1=k;
    }
    return;
}
int Findmin()
{
    int sum=0;
    for(int i=1;i<=n;++i)
    {
        if(!dele[i])
        {
            sum+=a[nd1][i];//最后更新点的割集
        }
    }
    return sum;
}
void Removepoint()
{
    dele[nd1]=true;
    for(int i=1;i<=n;++i)
    {
        if(!dele[i]&&i!=nd2)
        {
            a[i][nd2]+=a[i][nd1];//合并最后更新点
            a[nd2][i]+=a[nd1][i];
        }
    }
}
int main()
{
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        memset(a,0,sizeof(a));
        while(m--)
        {
            int i,j,k;
            scanf("%d %d %d",&i,&j,&k);
            ++i;++j;
            a[i][j]+=k;//重边
            a[j][i]+=k;
        }
        int ans=INF;
        memset(dele,false,sizeof(dele));//此点是否删除
        for(int w=1;w<n;++w)
        {
            Prim();
            ans=min(ans,Findmin());
            Removepoint();
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

 
posted on 2012-06-08 10:58  夜->  阅读(198)  评论(0编辑  收藏  举报