桐人的约会

题目描述

这是一个风和日丽的日子,桐人和诗乃在约会。他们所在的城市共有N个街区,和M条道路,每条道路连接两个不同的街区,并且通过一条道路需要花费一些时间。他们现在处于N号街区,正在享受幸福时光的桐人完全忘记了他的手机被亚丝娜安装了监控装置的事情,此时亚丝娜已经得知了桐人的位置以及他正在和一个妹子约会的事实,十分愤怒,于是从她所在的1号街区火速赶往N号街区。现在这个城市中有一条道路正在维修,不能通行,不过不论是哪条道路处于维修中,均存在一条路径可以从1号街区前往N号街区,而且亚丝娜一定会选取最短路前往N号街区。现在你很好奇,桐人的美好时光最多还能持续多久,即亚丝娜最多要花费多长的时间才能到达N号街区。

输入
第1行:两个正整数N,M,N表示街区个数,M表示道路数。
第2到M+1行 每行三个整数 u,v,w 表示存在一条连接u和v的道路,通过这条道路花费的时间为w
数据保证没有重边和自环

输出
一个整数,表示最多花费的时间。

输入样例
5 7
1 2 8
1 4 10
2 3 9
2 4 10
2 5 1
3 4 7
3 5 10

输出样例
27

说明
【数据规模】
30% N<=5, M<=10
60% N<=1000,M<=10000,w=1
100% N<=1000, M<=N*(N-1)/2,1<=w<=1000
.
.
.
.
.
分析
如果存在一条路径会影响1至n的最短路,那么这段路径一定存在于最短路上 ,所以找一条最短路,并枚举去掉的路径,找最短路中的最长路。
.
.
.
.
.
程序:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

int ls[2000001],zd[1001],cnt=0;

struct edge
{
	int to,w,next,wz,bz;
}e[2000001];

void add(int x,int y,int w)
{
    e[++cnt].to=y;e[cnt].w=w;e[cnt].next=ls[x];e[cnt].wz=cnt+1;e[cnt].bz=0;
    ls[x]=cnt;
    e[++cnt].to=x;e[cnt].w=w;e[cnt].next=ls[y];e[cnt].wz=cnt-1;e[cnt].bz=0;
    ls[y]=cnt;
}

int spfa(int s,int t,int flag)
{
	int d[1001];
	bool v[1001];
	memset(d,0x3f,sizeof(d));
	memset(v,false,sizeof(v));
    queue<int>q;
    q.push(s);
    d[s]=0;
    v[s]=true;
    while (!q.empty())
    {
        int tp=q.front();
		q.pop();
        for (int i=ls[tp];i;i=e[i].next)
            if (e[i].w+d[tp]<d[e[i].to]&&!e[i].bz)
            {
            	d[e[i].to]=d[tp]+e[i].w;
                if (flag==0) zd[e[i].to]=tp;
                if (!v[e[i].to])
                {
                    v[e[i].to]=true;
                    q.push(e[i].to);
                }
            }
        v[tp]=false;
    }
    return d[t];
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    spfa(1,n,0);
    int ans=0;
    for (int i=n;i;i=zd[i])
    {
        for (int j=ls[i];j;j=e[j].next)
            if (e[j].to==zd[i])
            {
                e[j].bz=e[e[j].wz].bz=1;
                int s=spfa(1,n,1);
                if (s>ans) ans=s;
                e[j].bz=e[e[j].wz].bz=0;
            }
    }
    printf("%d",ans);
    return 0;
}
在第 X 层主迷宫的尽头,亚丝娜遇到了一扇名为「阶律之门」的机关门。门心的光幕会依次显现一串不下降的整数,形成一条非降序序列。 给定一个整数序列 [v1, v2, …, vd],其评分定义为: 其中 len! = 1 · 2 · … · len。特别地,空序列的评分为 1。 对任意序列 [v1, v2, …, vd],记 m 为其所有子序列评分的最大值,则该序列的配置长度定义为:在评分等于 m 的所有子序列中,长度的最大值。 现在,光幕显现了一组非降序整数序列 [a1, a2, …, an](即 a1 ≤ a2 ≤ … ≤ an)。对每个 k=1,2,…,n,请你计算前缀 [a1, a2, …, ak] 的配置长度。 子序列的定义:序列 x 是序列 y 的子序列,当且仅当 x 可由 y 删除若干(可能为零或全部)元素得到。子序列由下标集合唯一确定,因此即使元素值相同但位置不同,也视为不同的子序列。 Input 每个测试包含多个测试用例。第一行包含测试用例的数量 t(1 ≤ t ≤ 104)。测试用例说明如下。 每个测试用例的第一行都包含一个整数 n(1 ≤ n ≤ 105)—— 给定序列的长度。 每个测试用例的第二行包含 n 个整数 a1, a2, …, an(1 ≤ ai ≤ n)—— 给定序列。保证其元素不递减。 保证所有测试用例中 n 的总不超过 5 × 105。 Output 对于每个测试用例,输出 n 个整数 —— 按 k 升序排列的序列 [a1, a2, …, ak] 的配置长度,每个整数后面紧接一个空格,每行最后紧接换行。 Sample Input 3 3 1 2 3 2 1 1 5 5 5 5 5 5 Sample Output 1 1 2 1 1 1 2 3 4 5 Hint 在第一个测试用例中: 对于前缀 [1]:所有子序列的最大评分为 1。评分等于 1 的子序列是 [1] 空序列 []。其中长度最大的子序列是 [1],长度为 1。因此,[1] 的配置长度是 1。 对于前缀 [1, 2]:最大评分为 2。评分等于 2 的唯一子序列是 [2],长度为 1。因此,[1, 2] 的配置长度是 1。 对于前缀 [1, 2, 3]:最大评分为 3。评分等于 3 的子序列有 [3] [2, 3]。其中长度最大的子序列是 [2, 3],长度为 2。因此,[1, 2, 3] 的配置长度是 2。 所以该测试用例的答案是:1 1 2
最新发布
10-27
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值