2019.01.22 SCU4444 Travel(最短路+bfs)

版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/86599694

传送门
题意简述:给出一张 n n 个点的完全图,有 m m 条边边权为 a a 其余点边权为 b b ,问从 1 1 n n 的最短路。


思路:分类讨论一波即可。

  1. ( 1 , n ) (1,n) 的边权为 a a ,那么只用求从 1 1 n n 不经过给出边的最短路,这个用 s e t + b f s set+bfs 解决。
  2. ( 1 , n ) (1,n) 的边权为 b b ,那么只用求从 1 1 n n 经过给出边的最短路,上 s p f a spfa 或者 d i j k s t r a dijkstra

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
const int N=1e5+5;
typedef long long ll;
const ll inf=1e18;
int n,m;
ll dis[N],a,b;
set<int>all,tmp;
vector<int>e[N];
typedef set<int>::iterator It;
inline ll bfs(int type){
	fill(dis+1,dis+n+1,inf);
	queue<int>q;
	if(!type){
		ll ret=b;
		q.push(1),dis[1]=0;
		while(!q.empty()){
			int x=q.front();
			q.pop();
			if(dis[x]>=ret)continue;
			for(ri i=0,v;i<e[x].size();++i)if(dis[v=e[x][i]]>dis[x]+a)dis[v]=dis[x]+a,q.push(v);
		}
		return min(ret,dis[n]);
	}
	ll ret=a;
	q.push(1),dis[1]=0;
	for(ri i=2;i<=n;++i)all.insert(i);
	while(!q.empty()){
		int x=q.front();
		q.pop();
		if(dis[x]>=ret)continue;
		if(x==n)return dis[x];
		for(ri i=0,v;i<e[x].size();++i){
			if(!all.count(v=e[x][i]))continue;
			else tmp.insert(v),all.erase(v);
		}
		for(It it=all.begin();it!=all.end();++it)dis[*it]=dis[x]+b,q.push(*it);
		all.swap(tmp),tmp.clear();
	}
	return ret;
}
int main(){
	while(~scanf("%d%d%lld%lld",&n,&m,&a,&b)){
		all.clear(),tmp.clear();
		for(ri i=1;i<=n;++i)e[i].clear();
		bool flag=0;
		for(ri i=1,u,v;i<=m;++i){
			u=read(),v=read();
			e[u].push_back(v),e[v].push_back(u);
			if((u==1&&v==n)||(u==n&&v==1))flag=1;
		}
		cout<<bfs(flag)<<'\n';
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/86599694