Light oj 1281 - New Traffic System 多状态最短路

题目大意:有向图,新计划的地铁,有k个计划新路,利用现有的铁路、k条新路和限定只能用d条新路,找出从0到n-1的最短路径

题目思路:用dist[u][use],储存使用use条新路,到达节点u的最短路径。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#define MAXSIZE 100005
#define INF 0x3f3f3f3f
#define LL long long

using namespace std;

//题意:有向图,新计划的地铁,有k个计划新路,利用现有的铁路、k条新路和限定只能用d条新路,找出从0到n-1的最短路径

typedef pair<int,int>p; //p.firsr储存节点,p.second储存到达该节点使用的新路的数目

int k,a[MAXSIZE],dist[MAXSIZE][15];

struct node
{
    int u;
    int v;
    int w;
    int op;
    int next;
}G[MAXSIZE];

void Add(int u,int v,int w,int op)
{
    G[k].u=u;
    G[k].v=v;
    G[k].w=w;
    G[k].op=op;
    G[k].next=a[u];
    a[u]=k++;
}

void spfa(int n,int d)
{
    queue<p> Q;
    dist[0][0]=0;
    Q.push(p(0,0));
    while(!Q.empty())
    {
        p k=Q.front();
        Q.pop();
        int u=k.first;
        int use=k.second;
        for(int i=a[u];i!=-1;i=G[i].next)
        {
            int v = G[i].v;
            int new_use = use + G[i].op;
            int new_d = dist[u][use] + G[i].w;
            if(dist[v][new_use] > new_d && new_use <= d) //更新使用new_use条新路到达v点的最短路
            {
                dist[v][new_use] = new_d;
                Q.push(p(v,new_use));
            }
        }
    }
}

void Init()
{
    for(int i=0;i<MAXSIZE;i++)
    {
        a[i]=-1;
        for(int j=0;j<15;j++)
            dist[i][j]=INF;
    }
    k=1;
}

int main()
{
    int T,n,m,b,d,cns=1;
    int u,v,w;
    scanf("%d",&T);
    while(T--)
    {
        Init();
        scanf("%d%d%d%d",&n,&m,&b,&d);
        while(m--)
        {
            scanf("%d%d%d",&u,&v,&w);
            Add(u,v,w,0);
            //Add(v,u,w,0);
        }
        while(b--)
        {
            scanf("%d%d%d",&u,&v,&w);
            Add(u,v,w,1);
           // Add(v,u,w,1);
        }
        spfa(n,d);
        int ans=INF;
        for(int i=0;i<=d;i++)
            ans=min(ans,dist[n-1][i]);
        if(ans < INF)
            printf("Case %d: %d\n",cns++,ans);
        else
            printf("Case %d: Impossible\n",cns++);
    }
    return 0;
}

时间: 2024-10-10 14:26:12

Light oj 1281 - New Traffic System 多状态最短路的相关文章

1281 - New Traffic System

  PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB The country - Ajobdesh has a lot of problems in traffic system. As the Govt. is very clever (!), they made a plan to use only one way roads. Two cities s and t are the two m

Light OJ 1037 - Agent 47(预处理状态压缩DP)

题目大意: 有个特工要执行任务,他会遭遇到最多15个目标,特工必须把他们全部杀死.当他杀死一个目标后他可以使用目标的武器来杀死其他人.因此他必须有一个杀人的顺序,使得他开枪的次数最小. 现在给你一个表,代表每种武器对每个目标可以造成多少伤害.并且你知道每个目标的血量.当这个目标的血量小于等于0的时候说明这个目标被杀死了.最初的时候这个特工只有一个枪,这个枪可以对一个目标造成1点伤害. 题目分析: 先把每个状态下最敌人造成的伤害预处理出来,然后再进行一次记忆化搜索. ===============

Lightoj 1281 New Traffic System (记忆化Dijkstra)

题意 给出若干个城市,城市和城市存在修好的道路,和存在一些没有修好的道路.要求你求出最多修d条路,求起点s到终点t的最短路径是 多少.给出城市数量n,城市编号从0 - n - 1 . n < 1e4 .给出修好的道路的条数m, 2 <= m <= 3 * 1e4 .给出存在但未被修好的路的条数k , 1 <= k <= 1e4 .最多修d条路, 0 <= d <= 10 .求s城市到t城市的最多修d条路的情况下的最短路. 分析 考虑dijkstra算法,朴素的没有

Light OJ 1406 Assassin`s Creed 状态压缩DP+强连通缩点+最小路径覆盖

题目来源:Light OJ 1406 Assassin`s Creed 题意:有向图 派出最少的人经过全部的城市 而且每一个人不能走别人走过的地方 思路:最少的的人能够走全然图 明显是最小路径覆盖问题 这里可能有环 所以要缩点 可是看例子又发现 一个强连通分量可能要拆分 n最大才15 所以就状态压缩 将全图分成一个个子状态 每一个子状态缩点 求最小路径覆盖 这样就攻克了一个强连通分量拆分的问题 最后状态压缩DP求解最优值 #include <cstdio> #include <cstri

Light OJ 1291 Real Life Traffic 双连通最少添边数

题目来源:Light OJ 1291 Real Life Traffic 题意:最少添加几条边 可以使全图边双连通 思路:缩点 重新构图 答案就是(叶子节点数+1)/ 2 #include <vector> #include <cstdio> #include <cstring> #include <stack> #include <algorithm> using namespace std; const int maxn = 10010; s

Light OJ 1316 A Wedding Party 最短路+状态压缩DP

题目来源:Light OJ 1316 1316 - A Wedding Party 题意:和HDU 4284 差不多 有一些商店 从起点到终点在走过尽量多商店的情况下求最短路 思路:首先预处理每两点之前的最短路 然后只考虑那些商店 个数小于15嘛 就是TSP问题 状态压缩DP搞一下 状态压缩姿势不对 有必要加强 #include <cstdio> #include <algorithm> #include <queue> #include <vector>

light oj 1236 【大数分解】

给定一个大数,分解质因数,每个质因子的个数为e1,e2,e3,--em, 则结果为((1+2*e1)*(1+2*e2)--(1+2*em)+1)/2. //light oj 1236 大数分解素因子 #include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <math.h> #include <ctype.h> #i

[2016-04-21][light]OJ[1234][Harmonic Number]

时间:2016-04-21 22:18:26 星期四 题目编号:[2016-04-21][light]OJ[1234][Harmonic Number] 题目大意:求∑nk=11kn∈(1,108),精确到10?8求∑k=1n1kn∈(1,108),精确到10?8 分析: 想法是打表,然后输出,但是直接打表会爆内存 解决办法,就是每隔100个来打表,节省1100的空间,然后从那个值开始计算到当前值解决办法,就是每隔100个来打表,节省1100的空间,然后从那个值开始计算到当前值 对应的整百就是n

Light OJ 1411 Rip Van Winkle`s Code 线段树成段更新

题目来源:Light OJ 1411 Rip Van Winkle`s Code 题意:3中操作 1种查询 求区间和 其中每次可以把一段区间从左到右加上1,2,3,...或者从右到左加上...3,2,1 或者把某个区间的数都置为v 思路:我是加了6个域 add是这段区间每个数都要加上add  add是这么来的 对与123456...这个等差数列 可能要分为2个区间 那么我就分成123和123 两个右边的等差数列每个数还应该加上3 所以右区间add加3 v是这个区间都要置为v 他的优先级最高 b是