sgu-226 Colored graph

 题目大意:

给你一个n(n<=200)个点,m(m<=n*n)的有向图,然后每条边都有一个颜色,然后要求求出1->n的一条最短路径,满足相邻的两条边不能是同一种颜色。输出最短路径长度。


解题思路:

一道很水的SPFA题目,只是要加上一点限制条件,我们可以用dist[ i ][ j ]表示第i个点并且是由j颜色的边连过来的最短路,一开始我们将所有的赋初始值为无穷大,然后令dist[1][0]=0,接着就是SPFA跑一遍就行了。

需要注意的是,这个图由自环,我们可能有时要通过自环来改变颜色,所以自环不能去除。



AC代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#define MIN(a,b) ((a)>(b)?(b):(a))

using namespace std;
struct bian_
{
	int num;
	int color;
	int next;
}bian[40010]={{0,0,0}};
int First[210]={0};
int n,m;
int dui[700010]={0};
int duip=0;
int dist[210][4]={{0}};
int hash[210]={0};

inline void Add(int p,int q,int r,int k)
{
	bian[k].num=q;
	bian[k].color=r;
	bian[k].next=First[p];
	First[p]=k;
	return;
}

inline void SPFA()
{
	memset(dist,0x3f3f3f3f,sizeof(dist));
	dui[++duip]=1;
	dist[1][0]=0;
	for(int i=1;i<=duip;i++)
	{
		int u=dui[i];
		hash[u]=0;
		dui[i]=0;
		for(int p=First[u];p!=0;p=bian[p].next)
		{
			int flag=0;
			int v=bian[p].num;
			int C=bian[p].color;
			if(dist[v][C]>dist[u][0]+1)
			{
				dist[v][C]=dist[u][0]+1;
				flag=1;
			}
			if(C!=1 && dist[v][C]>dist[u][1]+1)
			{
				dist[v][C]=dist[u][1]+1;
				flag=1;
			}
			if(C!=2 && dist[v][C]>dist[u][2]+1)
			{
				dist[v][C]=dist[u][2]+1;
				flag=1;
			}
			if(C!=3 && dist[v][C]>dist[u][3]+1)
			{
				dist[v][C]=dist[u][3]+1;
				flag=1;
			}
			
			if(flag==1 && hash[v]==0)
			{
				hash[v]=1;
				dui[++duip]=v;
			}
		}
	}
	return;
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int p,q,r;
		scanf("%d%d%d",&p,&q,&r);
		Add(p,q,r,i);
	}
	
	SPFA();
	int ans=MIN(MIN(dist[n][0],dist[n][1]),MIN(dist[n][2],dist[n][3]));
	if(ans==0x3f3f3f3f)
		cout<<-1<<endl;
	else cout<<ans<<endl;
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值