POJ_1062 昂贵的聘礼 Dijkstra

来源:互联网 发布:ubuntu 用户提权 编辑:程序博客网 时间:2024/06/12 13:13

题目连接 https://vjudge.net/problem/POJ-1062

本题为 Dijkstra 的应用


储存结构:

所有的替代品关系都可以储存在边上,酋长的承诺,应作为最终的终点“1”

另外应虚设一个结点“0”,“0”到“1->n”的n条有向边储存商品的原价


实现原理:

每一趟 Dijkstra 以枚举出来的最小等级跑一边,把“0”作为源点,最后取酋长承诺点“1”的 mincost[1] 值


最小等级枚举的说明:

图上一条路径可以看作整条交易链,宅整条交易的过程中高低等级悬殊不可以超过m,可以通过“枚举最小等级”的方法来实现

依次将“1->n”n个结点的等级作为最小等级,跑一边Dijkstra,沿着边向外拓展维护的时候,弧头结点等级与最小等级差超过 m,或者弧头节点等级小于最小等级,都是为边不可达


AC关键代码:

#define PP pair<int, int>#define INF 0x3f3f3f3fstruct edge{    int u, v;    int to, cost;    bool operator < (const edge &right) const {        return cost < right.cost;    }};const int maxn = 100 + 10;int m, n;vector<edge> G[maxn];int mincost[maxn];int value[maxn];int level[maxn];void init(){    cin >> m >> n;    edge buf;    int u, x;    for (int i = 1; i <= n; i ++){        scanf("%d%d%d", &value[i], &level[i], &x);        buf.to = i;        for (int j = 0; j < x; j ++){            scanf("%d%d", &u, &buf.cost);            G[u].push_back(buf);        }    }    for (int i = 1; i <= n; i ++){        buf.to = i;        buf.cost = value[i];        G[0].push_back(buf);    }}void manage(int minlevel){    priority_queue<PP, vector<PP>, greater<PP> > qq;    qq.push(PP(0, 0));    mem(mincost, INF);    mincost[0] = 0;    PP p;    while (!qq.empty()){        p = qq.top();        qq.pop();        int u = p.second;        if (p.first > mincost[u])   continue;        //refresh mincost        for (int i = 0; i < G[u].size(); i ++){            edge e = G[u][i];            if (!(level[e.to]-minlevel>m || level[e.to]<minlevel)){ //accessibility                if (mincost[e.to] > mincost[u]+e.cost){                    mincost[e.to] = mincost[u]+e.cost;                    qq.push(PP(mincost[e.to], e.to));                }            }        }    }}void solve(){    int ans = INF;    for (int j = 1; j <= n; j ++){        manage(level[j]);        ans = min(ans, mincost[1]);    }    cout << ans << endl;}


但是这里遇到一个费解的问题,如果正向思维,将“1”作为源点,依旧用“枚举最小等级”法,最后取所有节点最小的“mincost(最小路径长)+value(路径终点商品原价)”的话,测试结果是WA的

附WA关键代码:

const int maxn = 100 + 10;int m, n;vector<edge> G[maxn];int mincost[maxn];int value[maxn];int level[maxn];void init(){    cin >> m >> n;    edge buf;    int x;    for (int i = 1; i <= n; i ++){        scanf("%d%d%d", &value[i], &level[i], &x);        for (int j = 0; j < x; j ++){            scanf("%d%d", &buf.to, &buf.cost);            G[i].push_back(buf);        }    }}void manage(int minlevel){    priority_queue<PP, vector<PP>, greater<PP> > qq;    qq.push(PP(0, 1));    mem(mincost, INF);    mincost[1] = 0;    PP p;    while (!qq.empty()){        p = qq.top();        qq.pop();        int u = p.second;        if (p.first > mincost[u])   continue;        //refresh mincost        for (int i = 0; i < G[u].size(); i ++){            edge e = G[u][i];            if (!(level[e.to]-minlevel>m || level[e.to]<minlevel)){                if (mincost[e.to] > mincost[u]+e.cost){                    mincost[e.to] = mincost[u]+e.cost;                      qq.push(PP(mincost[e.to], e.to));                }            }        }    }}void solve(){    int ans = INF;    for (int j = 1; j <= n; j ++){        manage(level[j]);        for (int i = 1; i <= n; i ++){            mincost[i] += value[i];            ans = min(ans, mincost[i]);        }    }    cout << ans << endl;}



这里借鉴一下其他大佬的测试样例(上面的WA版代码能通过全部测试样例):

/*测试数据1:1 410000 3 22 80003 50001000 2 14 2003000 2 14 20050 2 05250测试数据2:1 510000 3 42 30003 20004 20005 90008000 2 33 50004 20005 70005000 1 02000 4 15 190050 1 04000测试数据3:3 810000 3 62 30003 20004 20005 90007 10008 50088000 2 33 50004 20005 70005000 1 16 10002000 4 15 190050 1 05000 1 17 40072000 4 15 190080 3 02950测试数据4:1 101324 0 01234 0 0255 0 067 0 056 0 02134 0 0456 0 02345 0 067 0 06436 0 01324测试数据5:  ///debug    一整条交易向上的等级差异都不能超过 m///这里帮助我纠正了第一次写的算法,当时以为等级差只是在某一条边的两端不能超过m1 410000 3 22 13 31000 2 24 13 11000 3 14 2100 4 0105测试数据6:3 510000 3 42 30003 20004 20005 90008000 2 33 50004 20005 70005000 1 02000 4 15 190050 1 03950测试数据7:0 510000 3 42 30003 20004 20005 90008000 2 33 50004 20005 70005000 4 02000 3 15 190050 2 04000*/


阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 经期螃蟹 经期吃螃蟹 经期可以吃柿子 经期食物 经期吃什么水果 经期带套可以做吗 益母草颗粒经期能喝吗 经期可以吃石榴 经期出血 经期吃火龙果 经期火龙果 经期喝茶 经期可以吃柿子吗 经期吃葡萄 经期吃香蕉 经期喝酒 经期可以吃石榴吗 经期香蕉 经期艾灸 经期巧克力 经期可以吃葡萄 经期能吃柚子 非经期有褐色分泌物无不适 经期怎么帮老公爽 经期吃猕猴桃 经期可以吃什么水果 经期猕猴桃 经期可以吃螃蟹 经期血块 经期能吃柿子 经期可以吃火龙果 经期能吃柚子吗 经期能吃螃蟹 经期喝奶茶 经期喝什么 经期芒果 经期吃巧克力 经期可以吃螃蟹吗 经期吃芒果 经期吃什么 经期可以吃葡萄吗