码迷,mamicode.com
首页 > 其他好文 > 详细

LightOJ 1380 – Teleport 【最小树形图】

时间:2015-04-14 21:42:14      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1380

最小树形图也就是有向图的最小生成树。普通的prim无法求解。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;

const int INF = 0x3f3f3f3f;
const int MAXN = 1010;
const int MAXM = 400100;

struct Edge
{
    int u, v, cost;
};
Edge edge[MAXM];
int pre[MAXN], id[MAXN], visit[MAXN], in[MAXN];
int zhuliu(int root, int n, int m, Edge edge[])
{
    int res = 0, u, v;
    while (1)
    {
        for (int i = 0; i < n; i++)
            in[i] = INF;
        for (int i = 0; i < m; i++)
            if (edge[i].u != edge[i].v && edge[i].cost < in[edge[i].v])
            {
                pre[edge[i].v] = edge[i].u;
                in[edge[i].v] = edge[i].cost;
            }
        for (int i = 0; i < n; i++)
            if (i != root && in[i] == INF)
                return -1;
        int tn = 0;
        memset(id, -1, sizeof(id));
        memset(visit, -1, sizeof(visit));
        in[root] = 0;
        for (int i = 0; i < n; i++)
        {
            res += in[i];
            v = i;
            while (visit[v] != i && id[v] == -1 && v != root)
            {
                visit[v] = i;
                v = pre[v];
            }
            if (v != root && id[v] == -1)
            {
                for (int u = pre[v]; u != v; u = pre[u])
                    id[u] = tn;
                id[v] = tn++;
            }
        }
        if (tn == 0)break;
        for (int i = 0; i < n; i++)
            if (id[i] == -1)
                id[i] = tn++;
        for (int i = 0; i < m;)
        {
            v = edge[i].v;
            edge[i].u = id[edge[i].u];
            edge[i].v = id[edge[i].v];
            if (edge[i].u != edge[i].v)
                edge[i++].cost -= in[v];
            else
                swap(edge[i], edge[--m]);
        }
        n = tn;
        root = id[root];
    }
    return res;
}
int g[MAXN][MAXN];


int a[100];
int sum[100];

void init(int n)
{
    for (int i = 0; i <= n; i++)
        for (int j = 0; j <= n; j++)
        {
            if (i == j)
                g[i][j] = 0;
            else
                g[i][j] = g[j][i] = INF;
        }
}

int main()
{
    int t, n, m, k,a,b,c;
    scanf("%lld",&t);
    for (int kk = 1; kk <= t; kk++)
    {
        scanf("%d%d%d", &n, &m, &k);
        init(n);
        while (m--)
        {
            scanf("%d%d%d", &a, &b, &c);
            if (g[a][b] > c)
                g[a][b] =  c;
        }
        int L = 0;
        for (int i = 0; i < n; i++)
            for (int j = 0; j <= n; j++)
            {
                if (g[i][j] < INF)
                {
                    edge[L].u = i;
                    edge[L].v = j;
                    edge[L++].cost = g[i][j];
                }
            }
        int ans = zhuliu(k,n,L,edge);
        if (ans != -1)
            printf("Case %d: %d\n", kk, ans);
        else 
            printf("Case %d: impossible\n", kk);
    }
    return 0;
}

LightOJ 1380 – Teleport 【最小树形图】

标签:

原文地址:http://blog.csdn.net/u014427196/article/details/45046821

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!