12.6日总结 最小度限制生成树 POJ 1639(含联通块dfs划分模板)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41661919/article/details/84865465

     今天看了 一道 有度数限制的最小生成树题目,按照书上给出的思路写的代码,思路的最后一步没有实现,可能没弄懂书上的意思。

http://poj.org/problem?id=1639

题意:

    大概是说在一张无向图中找一颗最小生成树,该树一定包含某“1”点,且该点的度数不能超过某值。

思路:

    先不考虑“1”点,对原图 dfs划分联通块,然后从每个联通块中找一条与“1”最近的路径添加到答案中。下一步在联通块内部求最小生成树。

     最后,遍历“1”点的所有边,如果某条边指向的终点不是已经生成的生成树的起点,判断其是否小于 已有生成树中从该点到“1”点路径中的最长边长度。有,替换旧边,,,直到找不到这样的边(最后这个地方理解的还有点问题)。

先把没写完的代码放在这里:

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include<algorithm>
#include <set>
#include <queue>
#include <stack>
#include<vector>
#include<map>
#include<ctime>
#define ll long long
using namespace std;
const int N=36;
int v[N];//联通块标号

int ver[N];//邻接表边N的终点
int edge[N*N+100];//邻接表边N的权值
int head[N];//邻接表点N的最后一条边
int next[N];//邻接表点边N的下一条边
int tot;//邻接表 中边数
int cnt;//联通块的数目

void add(int x,int y,int z)//邻接表加边
{
    ver[++tot]=y;
    edge[tot]=z;
    next[tot]=head[x];
    head[x]=tot;
}
void dfs(int x)//得到x所在的联通块
{
    v[x]=cnt;
    for(int i=head[x];i;i=next[i])
    {
        int y=ver[i];
        if(v[y])continue;
        dfs(y);
    }
}
int dis[N][N];
map<string,int>mm;
int num;
int d[N];//prime中以点N为终点的那条边;
bool flag[N];
int prime(int index,int pos,int nn)//联通块标号、起点
{
    memset(d,0,sizeof(d));
    memset(flag,0,sizeof(flag));
    d[pos]=0;
    for(int i=1;i<nn;++i)
    {
    
        int x=0;
        for(int j=1;j<=num;++j)
            if(!flag[j]&&((x==0)||d[j]<d[x])&&v[j]==index)x=j;
        flag[x]=1;
        for(int y=1;y<=num;++y)
        {
            if(!flag[y]&&v[y]==index)d[y]=min(d[y],dis[x][y]);
        }
    }
    int ans=0;
    for(int i=1;i<=num;++i)
    {
        if(v[i]==index)ans+=d[i];
    }
    return ans;
    
}
int main()
{
    int n;
    while(cin>>n)
    {
        memset(dis,0,sizeof(dis));
        tot=cnt=0;
        mm.clear();
        memset(v,0,sizeof(v));
        memset(ver,0,sizeof(ver));
        memset(head,0,sizeof(head));
        memset(next,0,sizeof(next));
        memset(edge,0,sizeof(edge));
        string s,t;
        int x;
        mm.insert(make_pair("Park",1));
        num++;
        for(int i=1;i<=n;++i)
        {
            cin>>s>>t>>x;
            int d1,d2;
            if(mm.find(s)==mm.end())
            {
                num++;
                mm.insert(make_pair(s,num));
                d1=num;

            }
            else
            {
                d1=mm.find(s)->second;
            }
            if(mm.find(t)==mm.end())
            {
                num++;
                mm.insert(make_pair(t,num));
                d2=num;
            }
            else
            {
                d2=mm.find(t)->second;
            }
            dis[d1][d2]=dis[d2][d1]=x;
            add(d1,d2,x);
        }
        
        int s;
        cin>>s;
        
        for(int i=2;i<=num;++i)
        {
            if(v[i])continue;
            cnt++;
            dfs(i);
        }
        /*if(cnt>s)
        {
            //无解
        }*/
        
        int ans=0;
        for(int i=1;i<=cnt;++i)
        {
            
            int minn=999999999;
            int pos;
            for(int j=1;j<=num;++j)
            {
                int nn=0;
                if(v[j]==i)
                {
                    nn++;
                    if(dis[j][1]<minn)minn=dis[j][1],pos=j;
                }
            }
            if(minn!=999999999)ans+=minn;
            ans+=prime(i,pos,nn);
        }
        
        
        
        
        
        
        


    }
}

猜你喜欢

转载自blog.csdn.net/qq_41661919/article/details/84865465