POJ1638 Picnic Planning (最小限制度生成树)

来源:互联网 发布:乔杉最新网络剧 编辑:程序博客网 时间:2024/06/03 11:18

 

时间:2011.6.1 19:58

POJ1638 Picnic Planning (最小限制度生成树)

题意:有一群兄弟去野餐,可以自己开车到目的地,或者开车到A的家里,然后和A一起去目的地。但目的地的停车场不一定容得下,如果每个人都自己开车去的话。所以这对连接到Park的边数有个限制。求他们总路径的最小值。

思路:最小限制度生成树,是指在无向图里找一颗最小生成树,使给定点V0的度数<=k;

步骤1.先求出最小m度限制生成树:将所有与Park连接的边去掉,得到一个或多个连通分量,各自求其最小生成树。当求出一个最小生成树T时,挑其中一个与Park最近的点,作为T的根,并以他为起点,求T上其他点的father节点。

        2.1,求m+1度限制生成树:先做处理,求出best[]数组,即比如best[3]=2,3Park路径上的最大的边权由2father[2]构成。之后,寻找一点x,使得g[source][x]-g[best[x]][father[bext[x]]]的和最小,并把边{best[x],father[best[x]]}去掉。

        3.当为K度限制生成树时,停止。

#include <iostream>#include <cstdio>#include <cstring>#include <map>#define N 30#define INF (1 << 30)using namespace std; int n, k, s, idx;int vis[N], dis[N], f[N], pre[N], mark[N], best[N];int g[N][N], edg[N][N];map<string, int> q; int dfs(int x){    int i;    for (i = 1; i <= idx; i++)    {        if (edg[i][x] && mark[i])        {            f[i] = x;            mark[i] = 0;            dfs(i);                 }    }    return 1;} int prim(int x){    int i, j, key, mini, sum = 0, root = -1;    for (i = 1; i <= idx; i++)    {       dis[i] = g[x][i];       pre[i] = x;    }    //pre[x] = s;    memset(mark, 0, sizeof(mark));    vis[x] = 1;    mark[x] = 1;    while (1)    {        mini = INF;        key = -1;        for (i = 1; i <= idx; i++)        {            if (! vis[i] && ! mark[i] && dis[i] < mini)            {                mini = dis[i];                key = i;             }        }         if (key == -1) break;        vis[key] = 1;        mark[key] = 1;        edg[pre[key]][key] = edg[key][pre[key]] = 1;        sum += dis[key];        for (i = 1; i <= idx; i++)        {            if (! vis[i] && ! mark[i] && g[key][i] < dis[i])            {                dis[i] = g[key][i];                pre[i] = key;             }        }    }    mini = INF;    for (i = 1; i <= idx; i++)    {        if (mark[i] && g[s][i] < mini)        {            mini = g[s][i];            root = i;               }    }    mark[root] = 0;    dfs(root);    f[root] = s;    return sum + mini;} int find_best(int x){    int tmp;    if (f[x] == s) return -1;    if (best[x] != -1) return best[x];    tmp = find_best(f[x]);    if (tmp != -1 && g[f[tmp]][tmp] > g[f[x]][x])        best[x] = tmp;    else        best[x] = x;    return best[x];} int solve(){    int i, j, m = 0, mst = 0, minadd, ax, bx, tmp, change;    memset(vis, 0, sizeof(vis));    memset(f, -1, sizeof(f));    memset(edg, 0, sizeof(edg));    vis[s] = 1;    for (i = 1; i <= idx; i++)    {        if (! vis[i])        {            mst += prim(i);            m++;         }    }    for (i = m + 1; i <= k; i++)    {        memset(best, -1, sizeof(best));        for (j = 1; j <= idx; j++)        {            if (best[j] == -1 && f[j] != s)                find_best(j);        }        minadd = INF;        for (j = 1; j <= idx; j++)        {            if (g[s][j] != INF && f[j] != s)            {                ax = best[j];                bx = f[ax];                tmp = g[s][j] - g[bx][ax];                if (tmp < minadd)                {                    minadd = tmp;                    change = j;                   }                   }        }        if (minadd >= 0) break;        mst += minadd;        ax = best[change];        bx = f[ax];        g[ax][bx] = g[bx][ax] = INF;        f[ax] = bx = s;        g[ax][bx] = g[bx][ax] = g[s][change];        g[s][change] = g[change][s] = INF;    }    return mst;} int main(){    int i, j, d, t1, t2, mst;    string s1, s2;    scanf("%d", &n);    for (i = 1; i <= N - 2; i++)    {        for (j = 1; j <= N - 2; j++)            g[i][j] = INF;    }    idx = 1;    q["Park"] = idx;    while (n--)    {        cin >> s1 >> s2;        scanf("%d", &d);        if (q.find(s1) == q.end())            t1 = q[s1] = ++idx;        else t1 = q[s1];        if (q.find(s2) == q.end())            t2 = q[s2] = ++idx;        else t2 = q[s2];            if (d < g[t1][t2])            g[t1][t2] = g[t2][t1] = d;    }    scanf("%d", &k);    s = 1;    mst = solve();    printf("Total miles driven: %d/n", mst);    system("pause");    return 0;}


     

原创粉丝点击