HDU 5636 (floyd算法)

Shortest Path
Time Limit:2000MS Memory Limit:131072KB 64bit IO Format:%I64d & %I64u
Submit

Status

Practice

HDU 5636
Description
There is a path graph G=(V,E) with n vertices. Vertices are numbered from 1 to n and there is an edge with unit length between i and i+1 (1i<n) . To make the graph more interesting, someone adds three more edges to the graph. The length of each new edge is 1 .

You are given the graph and several queries about the shortest path between some pairs of vertices.
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first line contains two integer n and m (1n,m105) – the number of vertices and the number of queries. The next line contains 6 integers a1,b1,a2,b2,a3,b3 (1a1,a2,a3,b1,b2,b3n) , separated by a space, denoting the new added three edges are (a1,b1) , (a2,b2) , (a3,b3) .

In the next m lines, each contains two integers si and ti (1si,tin) , denoting a query.

The sum of values of m in all test cases doesn’t exceed 106.
Output
For each test cases, output an integer S=(i=1mizi) mod (109+7) , where zi is the answer for i <script type="math/tex" id="MathJax-Element-3822">i</script>-th query.
Sample Input
1
10 2
2 4 5 7 8 10
1 5
3 1
Sample Output
7
题意:给你1—>n个点,每两个点距离是 1,再添加三条路,每条路的距离是1,求所给的式子
用floyd算法,我也是没有想过的,看了别人的题解才懂, 题目给的三条路的六个点,可以用floyd算法求这六个点之间的最短路,为什么呢?因为要求问的两个点之间的距离,那么这两个点之间的最小距离要么是它们的直接距离,要么就是过这六个点的两个,在用floyd算法就可以直接求出最短的了

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL long long
#define M 7

LL dist[M][M];
int a[M];
int abs(int a)
{
    return a < 0 ? (-a) : a;
}
void floyd()
{
    for(int k=1; k<M; k++)
    {
        for(int i=1; i<M; i++)
        {
            for(int j=1; j<M; j++)
            {
                dist[i][j] = dist[j][i] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
}
int main()
{
    int t, n, m;
    LL mod = 1e9+7;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &n, &m);
        for(int i=1; i<=6; i++)
        {
            scanf("%d", &a[i]);
        }
        for(int i=1; i<M; i++)//离散化一下使得 i, j直接表示 ai,aj
        {
            for(int j=1; j<M; j++)
            {
                dist[i][j] = abs(a[i] - a[j]);
            }
        }
        dist[1][2] = dist[2][1] = 1;//缩短距离
        dist[3][4] = dist[4][3] = 1;
        dist[5][6] = dist[6][5] = 1;
        floyd();//求六个点之间的最短距离
        LL ans = 0, flag = 0;
        int x, y;
        for(int i=1; i<=m; i++)
        {
            flag = 0;
            scanf("%d%d", &x, &y);
            flag = abs(x - y);
            for(int j=1; j<M; j++)
            {
                for(int k=1; k<M; k++)
                {
                    flag = min(flag, abs(x - a[k]) + abs(y - a[j]) + dist[k][j]);//计算最短距离
                    flag = min(flag, abs(y - a[k]) + abs(x - a[j]) + dist[k][j]);
                }
            }
            ans += (flag * i) % mod;
            ans %= mod;
        }
        printf("%lld\n", ans);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值