Kuskal/Prim POJ 1789 Truck History

 

题目传送门

题意:给出n个长度为7的字符串,一个字符串到另一个的距离为不同的字符数,问所有连通的最小代价是多少

分析:Kuskal/Prim: 先用并查集做,简单好写,然而效率并不高,稠密图应该用Prim而且要用邻接矩阵,邻接表的效率也不高。裸题但题目有点坑爹:(

 

Kruskal:

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;

const int MAXN = 2e3 + 10;
const int INF = 0x3f3f3f3f;
struct UF	{
	int rt[MAXN], rk[MAXN];
	void init(void)	{
		memset (rt, -1, sizeof (rt));
		memset (rk, 0, sizeof (rk));
	}
	int Find(int x)	{
		return (rt[x] == -1) ? x : rt[x] = Find (rt[x]);
	}
	void Union(int x, int y)	{
		x = Find (x), y = Find (y);
		if (x == y)	return ;
		if (rk[x] > rk[y])	{
			rt[y] = x;	rk[x] += rk[y] + 1;
		}
		else	{
			rt[x] = y;	rk[y] += rk[x] + 1;
		}
	}
	bool same(int x, int y)	{
		return Find (x) == Find (y);
	}
}uf;
char s[MAXN][10];
struct Node
{
    int u, v, w;
}node[MAXN*MAXN/2];
int n, tot;

bool cmp(Node x, Node y)    {return x.w < y.w;}

void get_w(int x)
{
    for (int i=1; i<x; ++i)
    {
        int res = 0;
        for (int j=0; j<7; ++j)
        {
            if (s[i][j] != s[x][j])    res++;
        }
        node[++tot].u = i;    node[tot].v = x;    node[tot].w = res;
    }
}

int main(void)        //POJ 1789 Truck History
{
    // freopen ("POJ_1789.in", "r", stdin);

    while (scanf ("%d", &n) == 1)
    {
        if (n == 0)    break;

        tot = 0;
        for (int i=1; i<=n; ++i)
        {
            scanf ("%s", s[i]);
            get_w (i);
        }
        sort (node+1, node+1+tot, cmp);

        int ans = 0;    uf.init ();
        for (int i=1; i<=tot; ++i)
        {
            int u = node[i].u;    int v = node[i].v;    int w = node[i].w;
            if (!uf.same (u, v))    {uf.Union (u, v);    ans += w;}
        }

        printf ("The highest possible quality is 1/%d.\n", ans);
    }

    return 0;
}

 

Prim:

/*
    模版搞错了,纠结半天。。。算法还是想清楚才行啊
*/
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

const int MAXN = 2e3 + 10;
const int INF = 0x3f3f3f3f;
int d[MAXN], w[MAXN][MAXN];
bool vis[MAXN];
int n;
char s[MAXN][10];

int Prim(int s)	{
	memset (vis, false, sizeof (vis));
	memset (d, INF, sizeof (d));	d[s] = 0;
	int ret = 0;
	for (int i=1; i<=n; ++i)	{
		int mn = INF, u = -1;
		for (int i=1; i<=n; ++i)	{
			if (!vis[i] && d[i] < mn)	mn = d[u=i];
		}
		if (u == -1)	return -1;
		vis[u] = true;	ret += d[u];
		for (int i=1; i<=n; ++i)	{
			if (!vis[i] && d[i] > w[u][i])	{
				d[i] = w[u][i];
			}
		}
	}
	return ret;
}

void get_w(int x)	{
    for (int i=1; i<x; ++i)	{
        int res = 0;
        for (int j=0; j<7; ++j)	{
            if (s[i][j] != s[x][j])    res++;
        }
        w[i][x] = w[x][i] = res;
    }
}

int main(void)	{
    while (scanf ("%d", &n) == 1)	{
        if (n == 0)    break;
        memset (w, INF, sizeof (w));
        for (int i=1; i<=n; ++i)	{
            scanf ("%s", s[i]);    get_w (i);
        }
        printf ("The highest possible quality is 1/%d.\n", Prim (1));
    }

    return 0;
}

 

posted @ 2015-06-13 16:58  Running_Time  阅读(206)  评论(0编辑  收藏  举报