送礼物

来源:互联网 发布:如何找淘宝代理加盟 编辑:程序博客网 时间:2024/04/28 15:57
题目详情

HeHe和XiXi在一个地方玩游戏,XiXi把N-1件礼物(HeHe以前送给XiXi的)分别藏在了另外N-1个地方,这些地方都能互相到达,且所有的边都是有方向的。

现在HeHe要做的事就是去那些地方找回那N-1件礼物给XiXi;

由于每一件礼物都有特殊的意义,所以XiXi要求HeHe每找到一件礼物,就必须马上返回XiXi所在的位置,对她说一句当年送她这件礼物的时候所说的话。

由于每走一个单位长度HeHe需要花费1分钟,XiXi还要求HeHe在最快的时间内把这些礼物带回来交给她,你能帮助HeHe么?


输入

测试数据有T组,每组测试数据开始为两个整数N和M,1 <= N,M <= 100000。

N代表所有的位置,M代表这些位置之间的长度

然后是M行,每行有三个数,u,v,w,即位置u和位置v之间有一条单向的边,距离为w;

你可以假设位置的编号是从1到N,XiXi的位置始终都在1;

输出

对于每组测试数据, 用一行输出HeHe所花费的最短时间。


提醒:问题一定有解。w的范围是100以内的整数。第一个T表示有多少组数据,比如T为2,就表示有两组输入数据。


答题说明

输入样例

1

3 3

1 2 4

2 3 5

3 1 6

输出样例

30


做完了回过头看,这个题与很久之前做过的最短路很像,其实是一样的,不过我不长记性,依旧折腾了一天才总算通过了。都快放弃了,不忍,看了看自己以前的代码,发现一个低调的BUG,顿时觉得自己脑洞大开。。。希望这是被堆排序绊倒的最后一次。

#include<iostream>#include<fstream>#include<vector>using namespace std;#define INF 0x7fffffff#define N 100010typedef struct Node//存储边 {int val;//边长 int to;//终点 }Node;Node to[N]; int heap[N];//指针式堆排序... int top;//堆边界 int get(int hp)//根据堆下标取值 {return to[heap[hp]].val;}void swap(int hp1, int hp2)//交换堆元素,以及数据关联 {int t = heap[hp1];heap[hp1] = heap[hp2];heap[hp2] = t;to[heap[hp1]].to = hp1;to[heap[hp2]].to = hp2;}void up(int hp) {while(hp / 2 > 0 && get(hp) < get(hp / 2)){swap(hp / 2, hp);hp /= 2;}}void make(int n)//如果up函数不坚持到顶,则make如下,否则可从n到n / 2(所有根节点都up过了,堆建立) {top = n;for(int i = 2; i <= n; i++){up(i);}}void down(void){    int root = 1;    while(2 * root <= top)     {        int next = 2 * root;//经典模式        if(next + 1 <= top && get(next) > get(next + 1))        {            next++;        }        if(get(root) <= get(next))        {            break;        }        swap(root, next);        root = next;    }}vector<Node> rel[N];vector<Node> relBack[N];int main(void){    int t, n, m;    //ifstream cin("in.txt");    cin >> t;    while(t-- > 0)    {        unsigned long long sum = 0;        int i, k, len;        cin >> n >> m;        for(i = 0; i < N; i++)        {        rel[i].clear();        relBack[i].clear();        }                for(int i = 0; i < m; i++)        {            int a, b;            Node x;            cin >> a >> b >> x.val;            x.to = b;            rel[a].push_back(x);            x.to = a;            relBack[b].push_back(x);        }        for(i = 2; i <= n; i++){to[i].val = INF;to[i].to = i - 1;//堆与to有一位的错位 heap[i - 1] = i; }len = rel[1].size();for(i = 0; i < len; i++)//直接邻居 {to[rel[1][i].to].val = rel[1][i].val;}make(n - 1);while(top > 0)//堆中还有元素{swap(1, top--);down();int place = heap[top + 1];sum += to[place].val;int len = rel[place].size();for(i = 0; i < len; i++){int dis = rel[place][i].to;int neo = rel[place][i].val + to[place].val;if(neo < to[dis].val){to[dis].val = neo;up(to[dis].to);}}}//反向最短路for(i = 2; i <= n; i++){to[i].val = INF;to[i].to = i - 1;heap[i - 1] = i;}len = relBack[1].size();for(i = 0; i < len; i++){to[relBack[1][i].to].val = relBack[1][i].val;}make(n - 1);while(top > 0){swap(1, top--);down();int place = heap[top + 1];sum += to[place].val;int len = relBack[place].size();for(i = 0; i < len; i++){int dis = relBack[place][i].to;int neo = relBack[place][i].val + to[place].val;if(neo < to[dis].val){to[dis].val = neo;up(to[dis].to);}}}cout << sum << endl;    }    return 0;}


0 0
原创粉丝点击