いっしょに面白くて最もショートします。
3760 ワード
http://codeforces.com/contest/29/problem/E
二つの動点の最短問題は、二つの点が同時に移動し、同時に同じ点に到達できないことを要求します。二つの点はずっと移動して待つことができなく、同時にそれぞれの目標点に到達する最短ルートを求めます。
状態空間[a][b][c](1<=a==n,1<=b==n,0<=c==1)は、動点0がaにあり、動点1がbにあり、現在は動点cに移動する番です。検索の初期状態は[1][n][0]で、終了状態は[n][1][0]で、bfsで結構です。
二つの動点の最短問題は、二つの点が同時に移動し、同時に同じ点に到達できないことを要求します。二つの点はずっと移動して待つことができなく、同時にそれぞれの目標点に到達する最短ルートを求めます。
状態空間[a][b][c](1<=a==n,1<=b==n,0<=c==1)は、動点0がaにあり、動点1がbにあり、現在は動点cに移動する番です。検索の初期状態は[1][n][0]で、終了状態は[n][1][0]で、bfsで結構です。
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <stack>
#include <queue>
#include <climits>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int MAXN(501);
const int MAXE(20010);
const int INFI((INT_MAX-1)/2);
const ULL LIM(1000000000000000000ull);
template<typename T>
bool checkmin(T &a, const T &b){
return b < a? (a = b, true): false;
}
template<typename T>
bool checkmax(T &a, const T &b){
return b > a? (a = b, true): false;
}
inline int lowb(int i){return i&-i;}
int gcd(int a, int b){
while(b){
int t = a%b;
a = b;
b = t;
}
return a;
}
bool vi[MAXN][MAXN][2];
int pre[MAXN][MAXN][2];
struct Q{
int a, b, c, d;
Q(){}
Q(int a_, int b_, int c_, int d_): a(a_), b(b_), c(c_), d(d_){}
} q[MAXN*MAXN*2];
int fr, ba;
// Graph
struct E{
int v;
E *next;
};
struct G{
E e[MAXE], *r;
E *h[MAXN];
void init(int n){
memset(h, 0, sizeof(h[0])*(n+1));
r = e;
}
void add(int u, int v){
r->v = v;
r->next = h[u];
h[u] = r++;
}
int bfs(int a, int b){
for(int i = 1; i <= b; ++i)
for(int j = 1; j <= b; ++j)
vi[i][j][0] = vi[i][j][1] = false;
q[0] = Q(a, b, 0, 0);
vi[a][b][0] = true;
while(fr <= ba){
Q t = q[fr++];
if(t.a == b && t.b == a && t.c == 0)
return t.d;
if(t.c){
for(E *i = h[t.b]; i; i = i->next)
if(!vi[t.a][i->v][0] && i->v != t.a){
q[++ba] = Q(t.a, i->v, 0, t.d+1);
vi[t.a][i->v][0] = true;
pre[t.a][i->v][0] = t.b;
}
}else{
for(E *i = h[t.a]; i; i = i->next)
if(!vi[i->v][t.b][1]){
q[++ba] = Q(i->v, t.b, 1, t.d+1);
vi[i->v][t.b][1] = true;
pre[i->v][t.b][1] = t.a;
}
}
}
return -1;
}
} g;
int p1[MAXN], p2[MAXN];
int main(){
int n, m, u, v;
scanf("%d%d", &n, &m);
g.init(n);
for(int i = 0; i < m; ++i){
scanf("%d%d", &u, &v);
g.add(u, v);
g.add(v, u);
}
int ans = g.bfs(1, n);
if(ans != -1){
printf("%d
", ans/2);
p1[ans/2] = n;
p2[ans/2] = 1;
int i1 = ans/2-1, i2 = ans/2-1;
int a = n, b = 1, c = 0;
for(int i = 0; i < ans; ++i){
if(c){
a = pre[a][b][c];
p1[i1--] = a;
}else{
b = pre[a][b][c];
p2[i2--] = b;
}
c ^= 1;
}
ans /= 2;
for(int i = 0; i <= ans; ++i){
if(i) printf(" ");
printf("%d", p1[i]);
}
printf("
");
for(int i = 0; i <= ans; ++i){
if(i) printf(" ");
printf("%d", p2[i]);
}
printf("
");
}else
printf("-1
");
return 0;
}