傳送門
次短路分兩類。
一、可以重複經過一個點的次短路。
可以在進行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 ;
}