• 选择合适的最短路--hdu3499


    [题目链接](http://acm.hdu.edu.cn/showproblem.php?pid=3499)

    刚看见题目,哦?不就是个最短路么,来,跑一下dijkstra记录最长路除个二就完事了 ,但是。。。。。。

    走红色的路是最佳方案,但是蓝色路的最短路跟短,我想错了;

    不久我又想,把每个边枚举一下,减半一个边,就跑一次dijstra,但是这太慢了,O(m*m*logm)

    拜拜了您內

    后来看了看网上的大佬,其实也可以枚举嘛,只要每一次枚举都是O(1)。显然需要预处理一下,正线边跑一次,反向边跑一次

    这样就可以了

    听说还可以分层图,没看懂,猜测了一下原理

    就这样了

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<map>
    #include<string>
    using namespace std;
    typedef long long ll;
    const int maxn = 5e5 + 100;
    const long long INF = 1e12;
    struct Node {
    	ll p, val;
    	Node(ll a, ll b) :p(a), val(b) {}
    };
    bool operator <(const Node a, const Node b) {
    	if (a.val > b.val) return true;
    	else return false;
    }
    int n, m;
    ll d1[maxn];
    ll d2[maxn];
    int vis[maxn];
    vector<Node>G[maxn];
    void insert(int be, int en, int len) {
    	G[be].push_back(Node(en, len));
    	return;
    }
    int dijstra(ll *dis, int be) {
    	for (int i = 0; i <= n; i++) {
    		vis[i] = 0;
    		dis[i] = INF;
    	}
    	dis[be] = 0;
    	priority_queue<Node>que;
    	que.push(Node(be, 0));
    	while (!que.empty()) {
    		Node ans = que.top();
    		que.pop();
    		if (vis[ans.p] == 0) {
    			vis[ans.p] = 1;
    			for (int i = 0; i < G[ans.p].size(); i++) {
    				int p = G[ans.p][i].p;
    				if (!vis[p] && dis[p] > dis[ans.p] + G[ans.p][i].val) {
    					dis[p] = dis[ans.p] + G[ans.p][i].val;
    					que.push(Node(p, dis[p]));
    				}
    			}
    		}
    	}
    	return 0;
    }
    map<string, int>ins;
    ll be_[maxn];
    ll en_[maxn];
    ll len_[maxn];
    int main() {
    	while (~scanf("%d %d", &n, &m)) {
    		ins.clear();//可得记得清空啊
    		string be, en;
    		ll len = 0;
    		int c = 0;
    		int cnt = 1;
    		while (m--) {
    			cin >> be >> en;
    			scanf("%lld", &len);
    			if (ins[be] == 0) ins[be] = cnt++;
    			if (ins[en] == 0) ins[en] = cnt++;
    			be_[c] = ins[be];
    			en_[c] = ins[en];
    			len_[c] = len;
    			c++;
    			insert(ins[en], ins[be], len);
    		}
    		cin >> be >> en;
    		if (ins[be] == 0) ins[be] = cnt++;
    		if (ins[en] == 0) ins[en] = cnt++;
    		dijstra(d2, ins[en]);
    		for (int i = 0; i <= n; i++) G[i].clear();
    		for (int i = 0; i < c; i++) {
    			insert(be_[i], en_[i], len_[i]);
    		}
    		dijstra(d1, ins[be]);
    		ll ans = d1[ins[en]];
    		if (ans == INF) {
    			printf("-1
    ");
    			continue;
    		}
    		for (int i = 1; i <= n; i++) {
    			for (int j = 0; j < G[i].size(); j++) {
    				ans = min(ans, d1[i] + d2[G[i][j].p] + G[i][j].val / 2);//每个顶点刷出来边试探
    			}
    		}
    		
    		printf("%lld
    ", ans);
    		for (int i = 0; i <= n; i++) G[i].clear();
    	}
    	return 0;
    }
    

      

    寻找真正的热爱
  • 相关阅读:
    innerHTML使用方法
    HDU 1426 Sudoku Killer
    Junit使用教程(一)
    HLS协议实现
    GPIO
    TraceView总结
    在kettle中实现数据验证和检查
    用户向导左右滑动页面实现之ImageSwitcher
    DWZ使用笔记
    oracle进程
  • 原文地址:https://www.cnblogs.com/lesning/p/11344242.html
Copyright © 2020-2023  润新知