最短路,前缀和优化连边,Dijkstra(UESTC 482,Charitable Exchange)
来源:互联网 发布:电梯破解软件 编辑:程序博客网 时间:2024/05/16 06:18
http://acm.uestc.edu.cn/#/problem/show/482
做了这道题目很有收获,一方面是熟练了优化连边的技巧,另一方面是对Dijkstra有了新的感悟。
关于优化连边的做法:
首先离散化,将1e9范围的数离散化,重新分配编号,这样最多有2e5个节点。
很显然,题目中的边是一种区间到单点的边,所以可以考虑线段树优化连边,可能是因为自己不够熟练,实现得不好,所以超内存了,但是看到有人这样做过了的。
但是有更好的优化方式,可以有更小常数的时空复杂度。
我们发现起点区间有一个性质,那就是右边界一定在最右边,一共有n个区间,所以就不用线段树优化了,可以后缀和优化,每个区间新建一个节点,直接区间到单点连边,然后每个区间和前面的区间连边,跑Dijkstra就好了。
关于对Dijkstra的新感悟:
主要是看了这篇博客的解法,在思考为什么正确的过程中对Dijkstra有了更深的认识。
http://blog.csdn.net/xinag578/article/details/50883997
博主说是广搜+优先队列优化,其实本质上就是Dijkstra的O(nlogn)优化啦。
n条边各用一次,因此最多产生n个新节点,放入优先队列中,时间复杂度O(nlogn)。
我一直疑惑为什么要挑一个t最小的点,然后把所有能用的边都用了,就可以得到正解。主要是疑惑为什么敢这么大胆地把用过的边都丢掉,难道保证这样做物尽其用了吗?
通过和Dijkstra的对比后发现,它们的做法其实没有任何区别,Dijkstra也是挑一个d最小的HeapNode,然后把所有从这个Node出发的边都用掉,更新其他节点。
由于每个节点只done一次,所以每条边只用一次,一共e条边,产生的新节点个数其实不太好估计,会有重复。仔细想了想最优是O(n)最差是O(n^2),但是那不重要,因为要取对数,平方就变成常数了,因此时间复杂度为O(elogn)。
下面讲一讲为什么敢这么大胆地把用过的边丢掉,即证明物尽其用了。
首先,边的作用就是为了更新节点,如果能保证这条边更新的情况是最完美的,那就必然物尽其用了。
何时才最完美呢?一条边的终端是固定的,边的长度也是固定的,那么只有当边的起始端的d是最小的时候,更新就是最完美的。
Dijkstra算法每次挑出d最小的未done的点,遍历所有出边,更细其他节点,此时的更新是最完美的,所以边用掉就可以丢了,不再用了。
上面那道题目也是如此,每次跳出t最小的点,然后把所有能用的边都用了,去更新其他节点,此时的更新也是最完美的,所以更新完后边也可以扔掉了。
因为m的范围太大,所以没法开那么大的数组来done,想done只能用stl或hash,但是不done不会错,只会导致时间复杂度升高,最多甚至可达立方级别,但是取对数后也变成常数了,所以也没关系。
优化连边代码:
#include<bits/stdc++.h>#define ls (now<<1)#define rs (ls|1)#define mid ((l+r)>>1)using namespace std;typedef long long ll;const ll maxn = 100010;const ll inf = LONG_LONG_MAX>>2;struct Edge{ ll from,to,dist;};struct HeapNode{ ll d,u; bool operator < (const HeapNode& rhs) const { return d>rhs.d; }};struct Dijkstra{ ll n,m; vector<Edge>edges; vector<ll>G[maxn<<2]; ll done[maxn<<2]; ll d[maxn<<2]; ll p[maxn<<2]; void init(ll n) { this->n=n; edges.clear(); for(ll i=1;i<=n;i++) G[i].clear(); } void AddEdge(ll from,ll to,ll dist) { edges.push_back((Edge){from,to,dist}); m=edges.size(); G[from].push_back(m-1); } void dijkstra(ll s) { for(ll i=1;i<=n;i++) { d[i]=inf; done[i]=0; } d[s]=0; priority_queue<HeapNode>q; q.push((HeapNode){0,s}); while(!q.empty()) { HeapNode now = q.top(); q.pop(); ll u = now.u; if(done[u]) continue; done[u]=1; for(ll i=0;i<(ll)G[u].size();i++) { Edge& e = edges[G[u][i]]; if(d[e.to]>d[e.from]+e.dist) { d[e.to]=d[e.from]+e.dist; p[e.to]=G[u][i]; q.push((HeapNode){d[e.to],e.to}); } } } }}DIJ;ll N,M;ll u[maxn];ll v[maxn];ll d[maxn];vector<ll>vec;map<ll,ll>id;ll cnt;void solve(){ id.clear(); cnt=0; vec.clear(); scanf("%lld %lld",&N,&M); for(ll i=0;i<N;i++) { scanf("%lld %lld %lld",v+i,u+i,d+i); if(u[i]==v[i]) { N--; i--; } else { if(u[i]>M) u[i]=M; if(v[i]>M) v[i]=M; vec.push_back(u[i]); vec.push_back(v[i]); } } vec.push_back(1); vec.push_back(M); sort(vec.begin(),vec.end()); vec.resize(unique(vec.begin(),vec.end())-vec.begin()); for(ll i=0;i<(ll)vec.size();i++) id[vec[i]]=++cnt; DIJ.init(cnt<<1); for(ll i=2;i<=cnt;i++) DIJ.AddEdge(i+cnt,i+cnt-1,0); for(ll i=1;i<=cnt;i++) DIJ.AddEdge(i,i+cnt,0); for(ll i=0;i<N;i++) { ll U=id[u[i]]; ll V=id[v[i]]; DIJ.AddEdge(U+cnt,V,d[i]); } DIJ.dijkstra(id[1]); ll ans = DIJ.d[id[M]]; if(ans==inf) puts("-1"); else printf("%lld\n",ans);}int main(){ ll T; scanf("%lld",&T); for(ll t=1;t<=T;t++) { printf("Case #%lld: ",t); solve(); } return 0;}
- 最短路,前缀和优化连边,Dijkstra(UESTC 482,Charitable Exchange)
- UESTC 482 Charitable Exchange
- UESTC 482 Charitable Exchange (线段树)
- uestc 482 Charitable Exchange 广搜+优先队列优化
- UESTC 482 Charitable Exchange(四川省赛B题)
- UESTC 482 Charitable Exchange(优先队列+bfs)
- UESTC 1558 Charitable Exchange
- UESTC 1558 Charitable Exchange
- UESTC_1558 Charitable Exchange 弦断树优化dp
- 最短路(dijkstra)
- 最短路(dijkstra)
- 最短路(Dijkstra)
- 最短路(Dijkstra)
- 最短路 (dijkstra )
- 最短路 (dijkstra)
- 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)
- HDU 2544 最短路(单源最短路 dijkstra / floyd / dijkstra(堆优化)/dijkstra+邻接链表+堆优化)
- poj1860Currency Exchange(最短路)
- POJ2892Tunnel Warfare
- Activity之间传递数据
- web项目部署到阿里云服务器
- codeforces 797e Array Queries 部分dp+暴力
- 文盲+wordpress搭建个人博客类网站
- 最短路,前缀和优化连边,Dijkstra(UESTC 482,Charitable Exchange)
- 堆排序
- redis阶段总结 -- php中redis的使用
- OGNL表达式struts2标签“%,#,$”
- 常用库
- Myeclipse10安装activiti插件包
- 不要给非static的元素加CSS3动画
- 矩阵快速幂的应用题 -- 魔力手环
- Itween笔记(第一节)