指路标问题

来源:互联网 发布:淘宝用户怎么贷款 编辑:程序博客网 时间:2024/06/05 20:39



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

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

#include <cstdio>#include <cstring>#include <queue>#define inf 0x3fffffff#define maxn 1005using 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++);}}


0 0