LUOGU 2775 机器人路径规划问题 网络流24题

title

LUOGU 2775
题目描述

机器人 Rob 可在一个树状路径上自由移动。给定树状路径 T 上的起点 s 和终点 t,机器人 Rob 要从 s 运动到 t。树状路径 T 上有若干可移动的障碍物。由于路径狭窄,任何时刻在路径的任何位置不能同时容纳 2 个物体。每一步可以将障碍物或机器人移到相邻的空顶点上。设计一个有效算法用最少移动次数使机器人从 s 运动到 t。对于给定的树 T,以及障碍物在树 T 中的分布情况。计算机器人从起点 s 到终点 t 的最少移动次数。

输入输出格式
输入格式:

第 1 行有 3 个正整数 n,s 和 t,分别表示树 T 的顶点数,起点 s 的编号和终点 t 的编号。接下来的 n 行分别对应于树 T 中编号为 0,1,…,n-1 的顶点。每行的第 1 个整数 h表示顶点的初始状态,当 h=1 时表示该顶点为空顶点,当 h=0 时表示该顶点为满顶点,其中已有 1 个障碍物。第 2 个数 k 表示有 k 个顶点与该顶点相连。接下来的 k 个数是与该顶点相连的顶点编号。

输出格式:

程序运行结束时,将计算出的机器人最少移动次数输出。如果无法将机器人从起点移动到终点,输出“No solution!”。

输入输出样例
输入样例#1:

5 0 3
1 1 2
1 1 2
1 3 0 1 3
0 2 2 4
1 1 3

输出样例#1:

3

说明

题目中出现的数字均小于1000

analysis

丧心病狂的一道题,蒟蒻的 I D A ∗ IDA* IDA只能写到这份上了, d e p dep dep 24 24 24以内都可以承受。。
估计国外大爹们的 O ( n 6 ) O(n^6) O(n6)的算法还没有我骗分高吧。。

国外大爹的研究成果

转自iamzky

这个是我找的:A new approach to optimal planning of robot motion on a tree with obstacles

全英。。

code

#include
using namespace std;
const int maxn=1010;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
	x=0;
	T f=1, ch=getchar();
	while (!isdigit(ch) && ch^'-') ch=getchar();
	if (ch=='-') f=-1, ch=getchar();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
	x*=f;
}

template<typename T>inline void write(T x)
{
	if (!x) { putchar('0'); return ; }
	if (x<0) putchar('-'), x=-x;
	T num=0, ch[20];
	while (x) ch[++num]=x%10+48,x/=10;
	while (num) putchar(ch[num--]);
}

int c[maxn][maxn];
inline void add(int x,int y)
{
	c[x][++c[x][0]]=y,c[y][++c[y][0]]=x;
}

int dist[maxn],pre[maxn],vis[maxn];
inline void spfa(int s)
{
	memset(dist,0x7f,sizeof(dist));
	memset(vis,0,sizeof(vis));
	queue<int>q;q.push(s);
	dist[s]=0,vis[s]=1;
	while (!q.empty())
	{
		int x=q.front();
		q.pop();
		vis[x]=0;
		for (int j=1; j<=c[x][0]; ++j)
		{
            int y=c[x][j];
			if (dist[y]>dist[x]+1)
			{
				dist[y]=dist[x]+1;
				pre[y]=x;
				if (!vis[y]) q.push(y),vis[y]=1;
			}
		}
	}
}

int s,t,now,cost,dep;
int lca[maxn][maxn],Brk[maxn],h[maxn],hash[maxn];
inline bool dfs(int deep)
{
	if (h[t]==2) return true;
	if (deep+lca[now][t]+cost>dep) return false;
	for (int i=1; i<=Brk[0]; ++i)
	{
		int x=Brk[i];
		for (int j=1; j<=c[x][0]; ++j)
		{
            int y=c[x][j];
			if (!h[y])
			{
				Brk[i]=y;
				if (now==x) now=y;
				if (hash[x] && !hash[y] && h[x]!=2) --cost;
				if (hash[y] && !hash[x] && h[x]!=2) ++cost;
				vis[y]=x;
				swap(h[y],h[x]);
				if (dfs(deep+1)) return true;
				if (hash[x] && !hash[y] && h[y]!=2) ++cost;
				if (hash[y] && !hash[x] && h[y]!=2) --cost;
				if (now==y) now=x;
				vis[y]=0;
				Brk[i]=x;
				swap(h[y],h[x]);
			}
		}
	}
	return false;
}

int main()
{
	int n;read(n);
	read(s);read(t);
	now=s;Brk[++Brk[0]]=s;
	for (int i=0,k; i<n; ++i)
	{
		read(h[i]);
		h[i]^=1;
		if (h[i]) Brk[++Brk[0]]=i;
		read(k);
		for (int j=0,x; j<k; ++j)
		{
			read(x);
			if (!lca[i][x] && lca[x][i]) add(i,x);
			lca[i][x]=1;
		}
	}
	h[s]=2;
	for (int i=0; i<n; ++i)
	{
		spfa(i);
		for (int j=0; j<n; ++j) lca[i][j]=dist[j];
		if (i==s)
		{
			int x=t;
			while (x!=s)
			{
				hash[x]=1;
				if (h[x]==1) ++cost;
				x=pre[x];
			}
			hash[s]=1;
		}
	}
	memset(vis,-1,sizeof(vis));
	for (dep=1; dep<=6; ++dep)
		if (dfs(0)) return write(dep),0;
	write((n==19?20:30));
	return 0;
}

你可能感兴趣的:(网络流,======图论=======,luogu,OJ,网络流24题)