指路标问题_i++

指路标问题_#include_02

一道学校内部测试赛的题目,对于这题,我们用最短路去处理。

首先我们看题,题目为我们最少需要改几条边能够走到终点,其实题意可以这样理解,问我们在尽量多走指路标所指方向下,最少能够走几条非指路标所指路线到达终点,那么我们采取的方法就是对指路标所指的路建立权值为0的边,给其他的路建立权值为1的边,求出到终点的最短路。


#include <cstdio>
#include <cstring>
#include <queue>
#define inf 0x3fffffff
#define maxn 1005
using namespace std;
struct Edge
{
int v, w, next;
}edge[10005];
int head[maxn], tot, dis[maxn], n;
bool vis[maxn];
void init()
{
tot = 0;
memset(head, -1, sizeof(head));
}
void addEdge(int u, int v, int w)
{
edge[tot].v = v;
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot++;
}
void SPFA(int u)
{
int v, w, i;
for(i = 1; i <= n; i++)
dis[i] = inf, vis[i] = false;
dis[u] = 0;
queue<int> q;
q.push (u);
vis[u] = true;
while(!q.empty())
{
u = q.front();
q.pop();
vis[u] = false;
for(i = head[u]; i != -1; i = edge[i].next)
{
w = edge[i].w;
v = edge[i].v;
if (dis[u] + w < dis[v])
{
dis[v] = dis[u] + w;
if (!vis[v])
{
q.push (v);
vis[v] = true;
}
}
}
}
}
int main()
{
int T,m,t=1;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &m);
init();
for(int i=0; i<m; i++)
{
int u,v;
scanf("%d%d", &u,&v);
addEdge(u,v,1);
addEdge(v,u,1);
}
for(int i=1; i<=n; i++)
{
int v;
scanf("%d", &v);
if(v != -1) addEdge(i,v,0);
}
SPFA(1);
if(dis[n] != inf)
printf("Case #%d: %d\n",t++, dis[n]);
else printf("Case #%d: -1\n",t++);
}
}