山东省第七届ACM大学生程序设计竞赛 C:Proxy

Problem Description

Because of the GFW (Great Firewall), we cannot directly visit many websites, such as Facebook, Twitter, YouTube, etc. But with the help of proxy and proxy server, we can easily get to these website.
    You have a list of several proxy servers, some of them can be connected directly but others can’t. But you can visit proxy servers through other proxy server by a one-way connection. 
    As we all know, the lag of internet visit will decide our feelings of the visit. You have a very smart proxy software which will find the least lag way to reach the website once you choose a directly reachable proxy server. 
    You know the lag of every connection. The lag of your visit is the all the lags in your whole connection. You want to minimize the lag of visit, which proxy server you will choose?

Input
    Multiple test cases, the first line is an integer T (T <= 100), indicating the number of test cases.
The first line of each test case is two integers N (0 <= N <= 1000), M (0 <= M <= 20000). N is the number of proxy servers (labeled from 1 to N). 
0 is the label of your computer and (N+1) is the label of the server of target website.
Then M lines follows, each line contains three integers u, v, w (0 <= u, v <= N + 1, 1 <= w <= 1000), means u can directly connect to v and the lag is w.
Output
    An integer in one line for each test case, which proxy server you will choose to connect directly. You can only choose the proxy server which can be connected directly from your computer.
If there are multiple choices, you should output the proxy server with the least label. If you can’t visit the target website by any means, output “-1” (without quotes). If you can directly visit the website and the lag is the least, output “0” (without quotes).
Example Input
4
3 6
0 1 10
1 2 1
2 4 4
0 3 2
3 2 1
3 4 7
2 4
0 2 10
0 1 5
1 2 4
2 1 7
1 3
0 2 1
0 1 2
1 2 1
1 3
0 2 10
0 1 2
1 2 1
Example Output
3
-1
0
1

#include <iostream>
#include<cstdio>
#include<queue>
#define maxn 1005
#define maxm 20005
using namespace std;
/*
注意:
    1.用邻接表来存储,用队列来维护
    2.每次仅对最短路估计值发生变化了的顶点的所有出边执行松弛操作
*/
struct Node
{
    int n;
    int first;
}dis[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    int n,m,i,k;
    //u、v、w数组大小要根据实际情况来设置,要比m的最大值大1;
    int u[maxm],v[maxm],w[maxm];
    //first要比n的最大值大1,next要比m的最大值大1;
    int first[maxn],next[maxm];
    int book[maxn]={0};//book数组用来记录哪些队列已经在队列中;
    queue<int> que;
    int inf=99999999;
    //顶点个数:n,边的条数m;
    while(T--)
    {

    scanf("%d%d",&n,&m);
    n=n+1;
    //初始化dis数组,这里是1号顶点到其余各个顶点的初始路程
    for(i=0;i<=n;i++)
    {
        dis[i].n=inf;
        dis[i].first=inf;
    }

    dis[0].n=0;
    dis[0].first=0;
    //初始化book数组,初始均为0,刚开始都不在队列中;
    for(i=0;i<=n;i++)
        book[i]=0;
    //初始化frist数组下标1~n均为-1,表示1~n顶点暂时都没有边;
    for(i=0;i<=n;i++)
        first[i]=-1;
    for(i=0;i<m;i++)
    {
        //读入每一条边
        scanf("%d%d%d",&u[i],&v[i],&w[i]);
        //下面两句是建立邻接表的关键
        if(u[i]==0)
        {
            dis[v[i]].first=v[i];
        }
        next[i]=first[u[i]];
        first[u[i]]=i;
    }
    //1号顶点入队
    que.push(0);
    book[0]=1;//标记1号顶点已经入队
    while(!que.empty())//队列不为空的时候循环
    {
        k=first[que.front()];//当前需要处理的队首指针
        while(k!=-1)//扫描当前顶点所有的边
        {
            if(dis[v[k]].n>dis[u[k]].n+w[k])//判断是否松弛成功
            {
                if(dis[u[k]].first!=0)
                    dis[v[k]].first=dis[u[k]].first;
                dis[v[k]].n=dis[u[k]].n+w[k];//更新顶点1到v[k]的路程
                //这的book数组用来判断v[k]是否在队列中
                //如果不适用一个数组来标记的话,判断一个顶点是否在队列中
                //每次都需要从队列的head到tail扫描一遍,很浪费时间
                if(book[v[k]]==0)//0表示不在队列中,将顶点v[k]加入队列
                {
                    que.push(v[k]);

                    book[v[k]]=1;//同时标记v[k]已经入队
                }
            }else if(dis[v[k]].n==dis[u[k]].n+w[k])
            {
                if(dis[u[k]].first!=0&&dis[u[k]].first<dis[v[k]].first)
                    dis[v[k]].first=dis[u[k]].first;
            }
            k=next[k];
        }
        //出队
        book[que.front()]=0;
        que.pop();
    }
    //输出1号顶点到其余各个顶点的最短路径

if(dis[n].first==inf)
    printf("-1\n");
else if(dis[n].first==n)
    printf("0\n");
else
    printf("%d\n",dis[n].first);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值