POJ 3164 最小樹形圖

看這個知識點純屬臨時抱佛腳,畢竟每年PKU時不時會出些圖論的偏知識點,大致瞭解一下思路也好。

用到的是朱劉算法,具體過程網上都有,我就不贅述了。貌似這道題還是我們WHUACM前輩們出的?題幹裏好多熟悉的名字啊。

要注意的是,初始化鄰接矩陣的時候,和最小生成樹一樣,都要賦爲Inf,否則最後求出來的值就成0了。


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define inf 99999999

const int maxn = 222;
int n, m;
double a[maxn][maxn];

struct node
{
    double x, y;
}p[maxn];

double get_dist(node p1, node p2)
{
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

double zhuliu()
{
    bool visit[maxn], flag[maxn];
    int pre[maxn];
    double sm = 0;
    int i, j, k;
    for(i = 0; i < n; i ++)
    {
        flag[i] = false;
        a[i][i] = inf;
    }
    pre[0] = 0;
    while(true)
    {
        for(i = 1; i < n; i ++)
        {
            if(flag[i]) continue;
            pre[i] = i;
            for(j = 0; j < n; j ++)
                if(!flag[j] && a[j][i] < a[pre[i]][i])
                    pre[i] = j;
            if(pre[i] == i)
                return -1;
        }
        for(i = 1; i < n; i ++)
        {
            if(flag[i])    continue;
            for(j = 0; j < n; j ++)
                visit[j] = false;
            visit[0] = true;
            j = i;
            do{
                visit[j] = true;
                j = pre[j];
            }while(!visit[j]);
            if(!j)  continue;
            i = j;
            do{
                sm += a[pre[j]][j];
                j = pre[j];
            }while(j != i);
            j = i;
            do{
                for(k = 0; k < n; k ++)
                    if(!flag[k] && a[k][j] < inf && k != pre[j])
                        a[k][j] -= a[pre[j]][j];
                j = pre[j];
            }while(j != i);
            for(j = 0; j < n; j ++)
            {
                if(j == i)  continue;
                for(k = pre[i]; k != i; k = pre[k])
                {
                    if(a[k][j] < a[i][j])   a[i][j] = a[k][j];
                    if(a[j][k] < a[j][i])   a[j][i] = a[j][k];
                }
            }
            for(j = pre[i]; j != i; j = pre[j])
                flag[j] = true;
            break;
        }
        if(i == n)
        {
            for(i = 1; i < n; i ++)
                if(!flag[i])
                    sm += a[pre[i]][i];
            break;
        }
    }
    return sm;
}

int main()
{
    while(~scanf("%d%d", &n, &m))
    {
        for(int i = 0; i < n; i ++)
            scanf("%lf%lf", &p[i].x, &p[i].y);
        for(int i = 0; i < n; i ++)
            for(int j = 0; j < n; j ++)
                a[i][j] = inf;
        for(int i = 0; i < m; i ++)
        {
            int u, v;
            scanf("%d%d", &u, &v);
            u --, v --;
            a[u][v] = get_dist(p[u], p[v]);
        }
        double ans = zhuliu();
        if(ans >= 0.0)
            printf("%.2lf\n", ans);
        else
            printf("poor snoopy\n");
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章