标签:sgu
题目大意:
给你一个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; }
标签:sgu
原文地址:http://blog.csdn.net/qq_21995319/article/details/42966939