不可\可重複經過點的次短路(POJ 3255 Roadblocks\ 迷陣突圍 )

傳送門

次短路分兩類。

一、可以重複經過一個點的次短路。

可以在進行dijkstra的過程中,更新兩個數組,分別是dis1,和dis2,代表最短路和次短路,每一次更新時,原來的dijkstra是隻更新最短路數組dis,但是現在你需要做的是,更新dis1,和dis2,兩個數組。能更新dis2,次短路數組的結點也必須入隊,這樣才能保證dis2,確實是次短路。

POJ 3255 AC code (dijkstra+priority queue)

#include<iostream>
#include<queue>
#include<cstring>
#include<string>
#include<sstream>
#include<map>
#include<vector>
#include<cstdio>
#include<set>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<stack>
#include<ctime>
using namespace std; 
#define rep(i,aa,bb) for(register int i=aa;i<=bb;i++)
#define rrep(i,aa,bb) for(register int i=aa;i>=bb;i--)
#define mset(var,val)	 memset(var,val,sizeof(var))
#define LL long long 
#define eps 0.000001
#define inf 0x7f7f7f7f
#define llinf 1e18
#define exp 0.000001
#define pai 3.141592654
#define random(x)   rand()%(x)
#define lowbit(x)   x&(-x)
inline int read()
{
	int x=0,y=1;char a=getchar();while ( a>'9' || a<'0'){if ( a=='-')y=-1;a=getchar();}
	while ( a>='0' && a<='9' ){	x=(x<<3)+(x<<1)+a-'0'; a=getchar();}return x*y;
}
#define N 200105
struct Ead {
	int u,v,w,nx; 
}e[N];int hea[N],tot = 0 ; 
int n,m;int dis1[N],dis2[N];
struct Node{
	int v,w; 
	Node (){}
	Node (int _v,int _w){
		v = _v;  w = _w; 
	}
	bool operator < (const Node &x)const {
		return w > x.w; 
	}
};
void init(){
	mset(hea,0);
}
void add_ead(int u,int v,int w){
	++tot; 
	e[tot].u = u ; e[tot].v = v; e[tot].w = w ; e[tot].nx = hea[u]; hea[u] = tot; 
}
void dijkstra(){
	priority_queue<Node>q; 
	mset(dis1,0x3f);	mset(dis2,0x3f);
	dis1[1] = 0 ; 
	Node now ,tem;
	q.push( Node(1,0) );
	while ( !q.empty() ){
		now = q.top();
		q.pop();
		if ( now.w > dis2[now.v] )		continue; 
		for (int i = hea[now.v]; i ; i = e[i].nx){
			int d =  now.w + e[i].w ;
			if ( dis1[ e[i].v ] > d ){
				swap(dis1[ e[i].v ] , d );
				q.push(Node( e[i].v,dis1[e[i].v] ));
			}
			if ( dis1[e[i].v] < d && dis2[e[i].v] > d){
				dis2[ e[i].v ] = d; 
				q.push(Node( e[i].v , dis2[e[i].v] ));
			}
		}
	}
}
int main()
{
//	freopen("D:\\垃圾程序存儲\\1.txt","r",stdin);
//	srand((int)time(0));
//	std::ios::sync_with_stdio(false);
	n = read(); m = read();
	init();
	rep(i,1,m){
		int a,b,c; 
		a = read(); b = read(); c = read();
		add_ead(a,b,c);
		add_ead(b,a,c);
	}
	dijkstra();
	printf("%d\n",dis2[n]);
	return 0;
}

二、不能重複經過一個點的次短路。

迷陣突圍

題意

有n個點,求1到n點的不能重複經過一個點的次短路。
輸入格式:
n m
以下n行,n個點的座標。
以下m行,m條雙向邊。
3 3
1 1
2 2
3 2
1 2
2 3
1 3

輸出格式:
1到n行次短路的長度。
2.41

dijksta

const int mmax = 210;
double mat[mmax][mmax];
double dis[mmax];
bool vis[mmax];
int pre[mmax];
int n; 
void dij(int st){
	rep(i,1,n){
		dis[i] = 1e20; vis[i] = 0; pre[i] = -1; 
	}
	dis[1] = 0 ; 
	int mink = -1; double minv = 1e20; 
	rep(ai,1,n){
		mink = -1; minv = 1e20 ; 
		rep(bi,1,n){
			if ( vis[bi] == 0 && dis[bi] < minv ){
				minv = dis[bi];	mink = bi;  
			}
		}
		if ( mink == -1 )	return ;
		vis[ mink ] = 1; 
		rep(bi,1,n){
			if ( vis[bi] == 0 && dis[bi] > minv + mat[mink][bi]){
				dis[ bi ] = minv + mat[mink][bi];
				pre[ bi ] = mink; 
			}
		}
	}
}

int x[mmax],y[mmax];
int pp[mmax];
double distan(int i,int j){
	return sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) );
}
int main(){
//	freopen("1.txt","r",stdin);
	int m; 
	cin>>n>>m; 
	for (int i = 1; i <= n; i++){
		cin>>x[i]>>y[i];
	}
	for (int i = 1; i <= n; i++){
		for (int j = 1; j <= n; j++){
			mat[i][j] = 1e20; 
		}
	}
	while ( m-- ){
		int u,v; 
		cin>>u>>v; 
		mat[u][v] = mat[v][u] = distan(u,v);
	}
	dij(1);
	if ( dis[n] >= 1e20 ){
		printf("-1\n");
		return 0;
	}
	rep(i,1,n)
		pp[i] = pre[i];
	
	double ans = 1e20  ;
	int now = n ;
	while ( pp[now] + 1 ){
		mat[ now ][ pp[now] ] = mat[ pp[now] ][ now ] = 1e20; 
		dij(1);
		ans = min( ans,dis[n] );
		mat[ now ][ pp[now] ] = mat[ pp[now] ][ now ] = distan(now,pp[now]); 
		now = pp[now];
	}
	if ( ans >= 1e20 ){
		cout<<"-1"<<endl; 
		return 0 ; 
	}
	printf("%.2lf\n",ans);
	return 0 ; 
}

dijksta+priority queue

const int mmax = 410;
bool x_y[mmax][mmax]; 
double dis[mmax];
bool vis[mmax];
int pre[mmax];
int n; 
struct Ead{
	int u,v,nx;double w; 
	Ead() {}
	Ead(int _u,int _v,double _w,int _nx){
		u = _u ; 		v = _v ; 		w = _w; 		nx = _nx; 
	}
}e[20009];int hea[mmax],tot; 
void add_ead(int u,int v,double w){
	++tot; 
	e[tot].u = u ; e[tot].v = v; e[tot].w = w; e[tot].nx = hea[u] ; hea[u] = tot; 
}
struct Node {
	int u;double w; 
	bool operator < (const Node &x )const{
		return w > x.w;
	}	
	Node (int _u,double _w){
		 u = _u ; 
		 w = _w ; 
	}
};
void dij(int st){
	rep(i,1,n){
		dis[i] = 1e20; vis[i] = 0; pre[i] = -1; 
	}
	dis[st] = 0 ; 
	priority_queue<Node> q; 
	q.push(Node(st,0));	
	while ( !q.empty() ){
		Node now = q.top() ; q.pop();
		if ( now.w != dis[now.u] )	continue; 
		for (int i = hea[now.u] ; i ; i = e[i].nx){
			if ( dis[e[i].v] > dis[e[i].u] + e[i].w && x_y[ e[i].u ][ e[i].v ] == 0){
				dis[e[i].v] = dis[ e[i].u ] + e[i].w; 
				pre[e[i].v] = e[i].u;
				q.push(Node(e[i].v,dis[e[i].v]));
			}
		}
	}		
}
int x[mmax],y[mmax];
int pp[mmax];
double distan(int i,int j){
	return sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) );
}
int main(){
//	freopen("1.txt","r",stdin);
	int m; 
	cin>>n>>m; 
	for (int i = 1; i <= n; i++){
		cin>>x[i]>>y[i];
	}
	mset(hea,0);
	while ( m-- ){
		int u,v; 
		cin>>u>>v; 
		add_ead(u,v,distan(u,v));
		add_ead(v,u,distan(u,v));
	}
	mset(x_y,0);
	dij(1);
	if ( dis[n] >= 1e20 ){
		printf("-1\n");
		return 0;
	}
	rep(i,1,n)
		pp[i] = pre[i];
	double ans = 1e20  ;
	int now = n ;
	while ( pp[now] + 1 ){
		mset(x_y,0);
		x_y[ now ][ pp[now] ] = x_y[ pp[now] ][ now ] = 1; 
		dij(1);
		ans = min( ans,dis[n] );
		now = pp[now];
	}
	if ( ans >= 1e20 ){
		cout<<"-1"<<endl; 
		return 0 ; 
	}
	printf("%.2lf\n",ans);
	return 0 ; 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章