HDOJ 4081: Qin Shi Huang's National Road System

来源:互联网 发布:订货系统的数据流程图 编辑:程序博客网 时间:2024/04/30 02:28

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4081


题目大意:

求一个图的生成树,

可以指定一条边为“魔法边”,使其边权变为0。

在此基础上,要求  “ '魔法边' 连接的两点的点权 / 生成树上其它边的边权"  最大。


算法:

首先,一定是在最小生成树上去掉一条边,然后在被分成的两部分间加上一条边。

因为把最小生成树去掉一条边的话,残留在两部分的生成树就是它们各自的最小生成树,否则把这条边加回来完全可以构成一个更优的最小生成树,矛盾。

然后我们枚举最小生成树上去掉的是哪条边,此时“生成树上其它边的边权",已经被确定。那么我们就直接在被分割出的两部分中各找一个点权最大的点连”魔法边“即可。


PS:1000个点的完全图跑krustal还是比较困难的,我写的prim。


代码如下:

#include <cstdio>#include <cstring>#include <cctype>#include <cstdlib>#include <ctime>#include <climits>#include <cmath>#include <iostream>#include <string>#include <vector>#include <set>#include <map>#include <list>#include <queue>#include <stack>#include <deque>#include <algorithm>#define inf 0x3f3f3f3f#define mp make_pair#define fi first#define nd secondusing namespace std;const int MAXN = 1100;int x[MAXN], y[MAXN], z[MAXN];int m1[MAXN], m2[MAXN];bool vis[MAXN];vector <pair <int, pair <int, int> > > edge;vector <pair <int, int> > nedge;queue <int> q;vector <int> mm[MAXN];priority_queue <pair <double, pair <int, int> > > pq;int n;double dis(int i, int j){    return sqrt((double)(x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));}int bfs(int s, int t){    memset(vis, 0, sizeof(vis));    vis[s] = true;    while(! q.empty())    {        q.pop();    }    vis[s] = true;    q.push(s);    int tmp = 0;    while(!q.empty())    {        int x = q.front();        q.pop();        tmp = max(tmp, z[x]);        for(int i = 0; i < mm[x].size(); i ++)        {            if(mm[x][i] == t)            {                continue;            }            if(vis[mm[x][i]])            {                continue;            }            q.push(mm[x][i]);            vis[mm[x][i]] = true;        }    }    return tmp;}int main(){    int cas;    scanf("%d", &cas);    while(cas --)    {        scanf("%d", &n);        for(int i = 0; i < n; i ++)        {            scanf("%d %d %d", &x[i], &y[i], &z[i]);            mm[i].clear();        }        memset(m1, -1, sizeof(m1));        memset(m2, -1, sizeof(m2));        memset(vis, 0, sizeof(vis));        edge.clear();        nedge.clear();        while(! pq.empty())        {            pq.pop();        }        for(int i = 1; i < n; i ++)        {            pq.push(mp(-dis(i, 0), mp(i, 0)));        }        vis[0] = true;        double sum = 0.0;        while(! pq.empty())        {            int y = - pq.top().fi;            int x = pq.top().nd.fi;            int p = pq.top().nd.nd;            pq.pop();            if(vis[x])            {                continue;            }            vis[x] = true;            mm[x].push_back(p);            mm[p].push_back(x);            nedge.push_back(mp(p, x));            sum += dis(x, p);            for(int i = 0; i < n; i ++)            {                if(!vis[i])                {                    pq.push(mp(-dis(i, x), mp(i, x)));                }            }        }        double ans = 0;        for(int filter = 0; filter < nedge.size(); filter ++)        {            int i = nedge[filter].fi;            int j = nedge[filter].nd;            int a = bfs(i, j);            int b = bfs(j, i);            ans = max(ans, (a + b) / (sum - dis(i, j)));        }        printf("%.2lf\n", ans);    }    return 0;}


原创粉丝点击