2018.10.30【校内模拟】有环无向图(最短路)(化边为点)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/83552046

传送门


解析:

首先,这道题没有负边权,写 S P F A SPFA 的不是想乱搞过题就是压根不会 D i j k s t r a Dijkstra 。然而真的有人乱搞过了题。。。然后在 O J OJ 上又被新数据卡 T T 了。

思路:

直接建边显然是 O ( d e g i 2 ) O(\sum deg_i^2) ,跑最短路就是 O ( m 2 l o g m ) O(m^2logm) ,肯定会gg。

考虑优化建图。
首先对于原题中路径的定义,考虑重新处理。将每个点的贡献变成进入它的边的权值+在入边意义下出边的贡献。

所以这样可以化边为点。

将每个点所有出边取出来,排个序,大的边向小的边连权值为 0 0 的边,表示在入边是大边的情况下,出边的贡献是0。小的依次向它的后继连权值为权值之差的边,表示如果走这条边出去,新增的贡献是差量。
然后所有边的反向边向它连权值为原权值的边,表示进入这个点之后要出去需要先计算它作为下一个点入边的代价。

这样建出来的边的规模就是 O ( m ) O(m) ,最多不会超过 6 m 6m 条边。

之后直接 D i j k s t r a Dijkstra 跑一下最短路,在终点的所有出边的反向边处考虑新的权值


代码(截止博客完工时,这份代码全OJ时空都是rank1,空间只有rank2的一半):

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline int getint(){
	re int num;
	re char c;
	while(!isdigit(c=gc()));num=c^48;
	while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
	return num;
}

cs int N=200005;
int last[N],nxt[N<<1],to[N<<1],ecnt=1;
int w[N<<1];
inline void addedge(int u,int v,int val){
	nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v,w[ecnt]=val;
	nxt[++ecnt]=last[v],last[v]=ecnt,to[ecnt]=u,w[ecnt]=val;
}

namespace NEWGRAPH{
	int last[N<<1],nxt[N*6],to[N*6],ecnt;
	int w[N*6];
	inline void addedge(int u,int v,int val){
		nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v,w[ecnt]=val;
	}
	ll dist[N<<1];
	bool vis[N<<1];
	priority_queue<pair<ll,int> ,vector<pair<ll,int> > ,greater<pair<ll,int> > > q;
	inline void Dijkstra(){
		memset(dist,0x3f,sizeof dist);
		for(int re e=::last[1],v=::to[e];e;v=::to[e=::nxt[e]]){
			dist[e]=::w[e];
			q.push(make_pair(dist[e],e));
		}
		while(!q.empty()){
			int u=q.top().second;q.pop();
			if(vis[u])continue;
			vis[u]=true;
			for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]]){
				if(dist[v]>dist[u]+w[e]){
					dist[v]=dist[u]+w[e];
					q.push(make_pair(dist[v],v));
				}
			}
		}
	}
}

int n,m;
signed main(){
	n=getint();
	m=getint();
	for(int re i=1;i<=m;++i){
		int u=getint(),v=getint(),val=getint();
		addedge(u,v,val);
	}
	for(int re u=1;u<=n;++u){
		vector<pair<int,int> > q;
		for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]])
		q.push_back(make_pair(w[e],e));
		
		sort(q.begin(),q.end());
		for(int re i=0;i<q.size();++i){
			if(i)NEWGRAPH::addedge(q[i].second,q[i-1].second,0);
			if(i+1<q.size())NEWGRAPH::addedge(q[i].second,q[i+1].second,q[i+1].first-q[i].first);
			NEWGRAPH::addedge(q[i].second^1,q[i].second,q[i].first);
		}
	}
	NEWGRAPH::Dijkstra();
	ll SP=0x3f3f3f3f3f3f3f3f;
	for(int re e=last[n];e;e=nxt[e]){
		SP=min(SP,NEWGRAPH::dist[e^1]+w[e]);
	}
	cout<<SP;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/83552046
今日推荐