CodeForces - 29E Quarrel【最短路】

题目链接:https://codeforces.com/contest/29/problem/E

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <climits>
#include <cstring>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <map>
#include <bitset>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
static const int INF=0x3f3f3f3f;
static const ll INFL=0x3f3f3f3f3f3f3f3f;
static const db EPS=1e-10;
static const db PI=acos(-1.0);
inline int read()
{
	int X=0; bool flag=1; char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
	while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
	if(flag) return X;
	return ~(X-1);
}
inline void write(int X)
{
	if(X<0) {X=~(X-1); putchar('-');}
	if(X>9) write(X/10);
	putchar(X%10+'0');
}
static const int MAXN=500+10;
vector<int> g[MAXN];
int d[1<<19],pre[1<<19];
int n,m,u,v;
int main()
{
	scanf("%d%d",&n,&m);
	while(m--)
	{
		scanf("%d%d",&u,&v);
		u--,v--;
		g[u].pb(v); g[v].pb(u);
	}
	memset(d,-1,sizeof(d));
	d[n-1]=0;
	queue<int> Q;
	Q.push(n-1);
	while(!Q.empty())
	{
		int t=Q.front();
		Q.pop();
		bool flag=false;
		if(t&(1<<18))
		{
			flag=true;
			t^=(1<<18);
		}
		int u=t>>9,v=t&511;
		if(flag) t^=(1<<18);
		if(flag)
		{
			for(int i=0;i<g[v].size();i++)
				if(g[v][i]!=u && d[(u<<9)|g[v][i]]==-1)
				{
					d[(u<<9)|g[v][i]]=d[t]+1;
					pre[(u<<9)|g[v][i]]=t;
					Q.push((u<<9)|g[v][i]);
				}
		}
		else
		{
			for(int i=0;i<g[u].size();i++)
				if(d[(1<<18)|(g[u][i]<<9)|v]==-1)
				{
					d[(1<<18)|(g[u][i]<<9)|v]=d[t];
					pre[(1<<18)|(g[u][i]<<9)|v]=t;
					Q.push((1<<18)|(g[u][i]<<9)|v);
				}
		}
	}
	int pos=(n-1)<<9;
	if(d[pos]==-1) puts("-1");
	else
	{
		printf("%d\n",d[pos]);
		vector<int> ans1,ans2;
		ans1.pb(n-1); ans2.pb(0);
		while(pos!=n-1)
		{
			pos=pre[pre[pos]];
			ans1.pb(pos>>9);
			ans2.pb(pos&511);
		}
		reverse(ans1.begin(),ans1.end());
		reverse(ans2.begin(),ans2.end());
		for(auto it:ans1) printf("%d ",it+1);
		puts("");
		for(auto it:ans2) printf("%d ",it+1);
		puts("");
	}
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值