【最短路】公共汽车

四、公共汽车

【问题描述】

     路人丁成为了一名新公交车司机,每个司机都有一张莫名其妙的牌子,牌子的正面写了拥有这个牌子的司机开的线路号,另外一面随便写了一个号码。但是路人丁却非常窘,因为给他的牌子两面写的都不是自己开的线路号。所以他决定跟其他人换,当然,所有的司机都只有当路人丁手里的牌子上某面写了自己的线路号时才愿意跟他换。所以路人丁想知道自己至少要换几次牌子才能换到一张写有自己线路号的牌子。

【输入】

     第一行包括一个整数K (K≤1000),表示车的数量(新车除外)。这些车的编号依次从l到K。接下来的K行,每行包括此车对应的线路号和牌子另一面的号码(长整范围的数字)。

      最后一行是安排路人丁开的公交车线路号以及给他的牌子上的号码。

【输出】

     首行是最少交换的次数M,接下来的M行顺序输出要交换牌子的车的编号。如果没有方案,则输出IMPOSSIBLE。

【样例输入】

4

8 5

5 4

7 4

1 5

4 1 8

【样例输出】

2

4

2


我们分别叫正面和背面A和B。两个点有边的条件是,A1=A2且B1=B2 或 A1=B2且B1=A2。

求出以n为源点的最短路,枚举每一个点。因为前面的交换都不需要满足路人丁,最后一次需要满足,所以最后一次要判断一下是否能够满足丁,然后找出最小值输出。


#include <string>
#include <cstring>
#include <cstdio>

long dist[1010];
bool used[1010];
long a[1010];
long b[1010];

struct node
{
	long ind;
	node* nxt;
};

node* head[1010];
long g[1010];
long n;

void output(long l)
{
	if (!l)
		return;
	output(g[l]);
	printf("%ld\n",l);
}

void dijkstra()
{
	memset(dist,0x7f,sizeof dist);
	for (node* vv=head[n];vv;vv=vv->nxt)
		dist[vv->ind] = 1;
	used[n] = true;
	for (long l=1;l<n;l++)
	{
		long nearest = 0x7f7f7f7f;
		long u = 0;
		for (long i=1;i<n+1;i++)
		{
			if (dist[i]<nearest&&!used[i])
			{
				nearest = dist[i];
				u = i;
			}
		}
		used[u] = true;
		for (node* vv=head[u];vv;vv=vv->nxt)
		{
			long v = vv->ind;
			if (!used[v]&&dist[v]>dist[u]+1)
			{
				dist[v] = dist[u]+1;
				g[v] = u;
			}
		}
	}
}

long getint()
{
	long rs=0;bool sgn=1;char tmp;
	do tmp = getchar();
	while (!isdigit(tmp)&&tmp-'-');
	if (tmp=='-'){tmp=getchar();sgn=0;}
	do rs=(rs<<3)+(rs<<1)+tmp-'0';
	while (isdigit(tmp=getchar()));
	return sgn?rs:-rs;
}

void insert(long a,long b)
{
	node* nn = new node;
	nn->ind = b;
	nn->nxt = head[a];
	head[a] = nn;
}
int main()
{
	freopen("bus.in","r",stdin);
	freopen("bus.out","w",stdout);
	n = getint();
	for (long i=1;i<n+1;i++)
	{
		a[i] = getint();
		b[i] = getint();
	}
	long des = getint();
	n ++;
	a[n] = getint();
	b[n] = getint();
	for (long i=1;i<n+1;i++)
	{
		for (long j=1;j<n;j++)
		{
			if (i == j) continue;
			if (a[i]==a[j]||b[i]==a[j])
			{
				insert(i,j);
			}
		}
	}
	dijkstra();
	long ans = 0x7f7f7f7f;
	long mov = 0;
	for (long i=1;i<n;i++)
		if (a[i]==des||b[i]==des)
			if  (dist[i] < ans)
			{
				ans = dist[i];
				mov = i;
			}
	if (ans == 0x7f7f7f7f)
		printf("IMPOSSIBLE");
	else
	{
		printf("%ld\n",ans);
		//output(mov);
	}
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值