1. 程式人生 > >12.6日總結 最小度限制生成樹 POJ 1639(含聯通塊dfs劃分模板)

12.6日總結 最小度限制生成樹 POJ 1639(含聯通塊dfs劃分模板)

     今天看了 一道 有度數限制的最小生成樹題目,按照書上給出的思路寫的程式碼,思路的最後一步沒有實現,可能沒弄懂書上的意思。

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);
        }
        
        
        
        
        
        
        


    }
}