HDU6331&&18多校3M Walking Plan 【分块+DP】

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)

Total Submission(s): 633    Accepted Submission(s): 229

 

Problem Description

There are n intersections in Bytetown, connected with m one way streets. Little Q likes sport walking very much, he plans to walk for q days. On the i-th day, Little Q plans to start walking at the si-th intersection, walk through at least ki streets and finally return to the ti-th intersection.
Little Q's smart phone will record his walking route. Compared to stay healthy, Little Q cares the statistics more. So he wants to minimize the total walking length of each day. Please write a program to help him find the best route.

 

 

Input

The first line of the input contains an integer T(1≤T≤10), denoting the number of test cases.
In each test case, there are 2 integers n,m(2≤n≤50,1≤m≤10000) in the first line, denoting the number of intersections and one way streets.
In the next m lines, each line contains 3 integers ui,vi,wi(1≤ui,vi≤n,ui≠vi,1≤wi≤10000), denoting a one way street from the intersection ui to vi, and the length of it is wi.
Then in the next line, there is an integer q(1≤q≤100000), denoting the number of days.
In the next q lines, each line contains 3 integers si,ti,ki(1≤si,ti≤n,1≤ki≤10000), describing the walking plan.

 

题意:给定一个 n 个点,m 条边的有向图,q 次询问 s 到 t 经过至 少 k 条边的最短路。(2 ≤ n ≤ 50, 1 ≤ m, k ≤ 10000, 1 ≤ q ≤ 100000)

分析:比赛时没有思路,后来看啦题解补啦。由于查询次数和至少经过的边数都比较大,如果提前预处理,复杂度是10000*50*50*50,很明显会超时。每次单独计算消耗时间更多。所以可以采用分块的算法来节省时间。此题的分块是提前预处理出任意两点经过至少100*i和i条边的最小距离(i<=100),这个预处理过程可以用DP来完成。然后每次求解答案时,就可以在O(n)的时间内通过枚举中间点计算出来。(例于,要求1到n至少经过1234条边的最小距离,求枚举点p,1经过至少1200条边和p点到n至少经过34条边的距离和的最小值)

#include
#define LL long long
using namespace std;
const int N=110;
const int INF=0x3f3f3f3f;
int d[N][N][N],g[N][N][N],a[N][N],b[N][N]; //d数组存任意两点至少经过100*i条边的最小值
                                           //g数组存任意两点至少经过i条边的最小值
int main()
{
    int TA,n,m,T,u,v,x,y,z,num;
    scanf("%d",&TA);
    while(TA--)
    {
        scanf("%d%d",&n,&m);
        memset(g,0x3f,sizeof(g));
        memset(d,0x3f,sizeof(d));
        for(int i=1; i<=n; i++)
            g[0][i][i]=d[0][i][i]=0;
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            if(g[1][x][y]>z)
                g[1][x][y]=z;
        }
        for(int l=1; l

 

你可能感兴趣的:(【动态规划】-DP杂)