题意:n个点,电车从A到B。每个点可以到其它ki个点,但默认只通往给出的第一个点,如果要到其它点,必须改变轨道方向一次。问A到B最少改变几次轨道方向。
总结:裸裸的最短路,所以,狠狠的把Floyd, Bellman, Dijkstra, Spfa都给撸了一遍。一个字,爽!
一道裸体,题意比较坑,于是试着写了一发dij的优先队列优化(V*log(E))和flyd。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define LL int
const int MAX=1000000000;
int n,A,B;
int mat[200][200];
struct node{
LL x,d;
node(LL a,LL b){ x=a,d=b;}
bool operator <(const node &a) const
{
if(d==a.d) return x>a.x;
return a.d<d;
}
};
vector<node>p[200];
void init()
{
for(int i=0;i<200;i++) p[i].clear();
for(int i=0;i<=n;i++)
{
for(int j=0;j<=n;j++)
{
if(i==j) mat[i][j]=0; //自身点初始化为0
else
mat[i][j]=MAX;
}
}
}
int floyd()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
mat[j][k]=min(mat[j][k],mat[j][i]+mat[i][k]); //以最外成作为松弛点
}
}
}
if(mat[A][B]>=MAX) return -1;
else return mat[A][B];
}
int Dijkstra()
{
int dis[200];
for(int i=0;i<=n;i++) dis[i]=MAX;
dis[A]=0;
priority_queue<node>q;
q.push(node(A,dis[A]));
while(!q.empty())
{
node x=q.top();
q.pop();
for(int i=0;i<p[x.x].size();i++)
{
node y=p[x.x][i];
if(dis[y.x]>x.d+y.d)
{
dis[y.x]=x.d+y.d;
q.push(node(y.x,dis[y.x]));
}
}
}
// for(int i=0;i<=n;i++) printf("%d ",dis[i]);
if(dis[B]==MAX) return -1;
else return dis[B];
}
int main()
{
while(scanf("%d%d%d",&n,&A,&B)!=EOF)
{
init();
for(int i=1;i<=n;i++)
{
int num;
scanf("%d",&num);
for(int j=1;j<=num;j++)
{
int end;
scanf("%d",&end);
if(j==1)
{
p[i].push_back(node(end,0));
// p[end].push_back(node(i,0));
mat[i][end]=0;
}
else
{
p[i].push_back(node(end,1));
// p[end].push_back(node(i,1));
mat[i][end]=1;
}
}
}
int sum=0;
//sum=floyd();
sum=Dijkstra();
printf("%d\n",sum);
}
return 0;
}