4386: [POI2015]Wycieczki

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 197  Solved: 49
[Submit][Status][Discuss]

Description

给定一张n个点m条边的带权有向图,每条边的边权只可能是1,2,3中的一种。
将所有可能的路径按路径长度排序,请输出第k小的路径的长度,注意路径不一定是简单路径,即可以重复走同一个点。

Input

第一行包含三个整数n,m,k(1<=n<=40,1<=m<=1000,1<=k<=10^18)。
接下来m行,每行三个整数u,v,c(1<=u,v<=n,u不等于v,1<=c<=3),表示从u出发有一条到v的单向边,边长为c。
可能有重边。

Output

包含一行一个正整数,即第k短的路径的长度,如果不存在,输出-1。

Sample Input

6 6 11
1 2 1
2 3 2
3 4 2
4 5 1
5 3 1
4 6 3

Sample Output

4

HINT

长度为1的路径有1->2,5->3,4->5。
长度为2的路径有2->3,3->4,4->5->3。
长度为3的路径有4->6,1->2->3,3->4->5,5->3->4。
长度为4的路径有5->3->4->5。

Source

鸣谢Claris

Solution

边权只有1,2,3三种,可以考虑拆点,那么只有边权为1的边了

那么显然可以DP,但是时间复杂度不允许

考虑用矩阵乘法去转移

这里比较优秀的方法是基于倍增的矩阵乘法

总复杂度是$O(n^{3}logK)$

答案会很大,乘爆longlong需要特判

这题细节非常多!

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
inline long long read()
{
long long x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define MAXN 130
int id[MAXN][],ID,N,M,B;
long long K,V[MAXN*];
struct MatrixNode{long long a[MAXN][MAXN];}a[],b,c,tmp;
MatrixNode operator * (const MatrixNode &A,const MatrixNode &B)
{
MatrixNode C; memset(C.a,,sizeof(C.a));
for (int i=; i<=ID; i++)
for (int j=; j<=ID; j++)
for (int k=; k<=ID; k++)
if (A.a[i][k]&&B.a[k][j])
{
if (A.a[i][k]< || B.a[k][j]<) {C.a[i][j]=-; break;}
if (A.a[i][k]>K/B.a[k][j]) {C.a[i][j]=-; break;}
C.a[i][j]+=A.a[i][k]*B.a[k][j];
if (C.a[i][j]>K) {C.a[i][j]=-; break;}
}
return C;
}
bool Check()
{
long long re=;
for (int i=; i<=ID; i++)
if (tmp.a[][i] && V[i])
{
if (tmp.a[][i]<) return ;
if (tmp.a[][i]>K/V[i]) return ;
re+=tmp.a[][i]*V[i];
if (re>K) return ;
}
return re<K;
}
int main()
{
N=read(),M=read(),K=read();
for (int i=; i<=N; i++) for (int j=; j<=; j++) id[i][j]=++ID;
for (int i=; i<=N; i++)
{
for (int j=; j<=; j++)
a[].a[id[i][j]][id[i][j+]]++;
a[].a[][id[i][]]++;
}
a[].a[][]++;
for (int x,y,z,i=; i<=M; i++) x=read(),y=read(),z=read(),a[].a[id[y][z-]][id[x][]]++,V[id[y][z-]]++;
for (int i=; (1LL<<i)<=K*; B=++i); B--;
for (int i=; i<=B; i++) a[i]=a[i-]*a[i-];
long long ans=;
for (int i=; i<=ID; i++) c.a[i][i]=;
for (int i=B; ~i; i--)
{
tmp=c*a[i];
if (Check()) ans|=(1LL<<i),memcpy(c.a,tmp.a,sizeof(tmp.a));
}
ans++;
if (ans>K*) {puts("-1"); return ;}
else printf("%lld\n",ans);
return ;
}

模拟赛的时候,没认真读题,以为是“魔法猪学院”类似的...等到半场才发现.....然后GG

【BZOJ-4386】Wycieczki DP + 矩阵乘法的更多相关文章

  1. 【bzoj2004】[Hnoi2010]Bus 公交线路 状压dp+矩阵乘法

    题目描述 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计 ...

  2. 【bzoj3329】Xorequ 数位dp+矩阵乘法

    题目描述 输入 第一行一个正整数,表示数据组数据 ,接下来T行每行一个正整数N 输出 2*T行第2*i-1行表示第i个数据中问题一的解, 第2*i行表示第i个数据中问题二的解, 样例输入 1 1 样例 ...

  3. 【BZOJ 3326】[Scoi2013]数数 数位dp+矩阵乘法优化

    挺好的数位dp……先说一下我个人的做法:经过观察,发现这题按照以往的思路从后往前递增,不怎么好推,然后我就大胆猜想,从前往后推,发现很好推啊,维护四个变量,从开始位置到现在有了i个数 f[i]:所有数 ...

  4. bzoj 3329: Xorequ【数位dp+矩阵乘法】

    注意第一问不取模!!! 因为a+b=a|b+a&b,a^b=a|b-a&b,所以a+b=a^b+2(a&b) x^3x==2x可根据异或的性质以转成x^2x==3x,根据上面的 ...

  5. BZOJ 3329 Xorequ 数字DP+矩阵乘法

    标题效果:特定n,乞讨[1,n]内[1,2^n]差多少x满足x^3x=2x x^3x=2x相当于x^2x = 3x 和3x=x+2x 和2x=x<<1 因此x满足条件IFFx&(x ...

  6. 【BZOJ】1009: [HNOI2008]GT考试(dp+矩阵乘法+kmp+神题)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1009 好神的题orzzzzzzzzzz 首先我是连递推方程都想不出的人...一直想用组合来搞..看来 ...

  7. bzoj 4818: [Sdoi2017]序列计数【容斥原理+dp+矩阵乘法】

    被空间卡的好惨啊---- 参考:http://blog.csdn.net/coldef/article/details/70305596 容斥,\( ans=ans_{没有限制}-ans{没有质数} ...

  8. Luogu P4643 【模板】动态dp(矩阵乘法,线段树,树链剖分)

    题面 给定一棵 \(n\) 个点的树,点带点权. 有 \(m\) 次操作,每次操作给定 \(x,y\) ,表示修改点 \(x\) 的权值为 \(y\) . 你需要在每次操作之后求出这棵树的最大权独立集 ...

  9. LOJ.6074.[2017山东一轮集训Day6]子序列(DP 矩阵乘法)

    题目链接 参考yww的题解.本来不想写来但是他有一些笔误...而且有些地方不太一样就写篇好了. 不知不觉怎么写了这么多... 另外还是有莫队做法的...(虽然可能卡不过) \(60\)分的\(O(n^ ...

随机推荐

  1. C语言操作文件

    #include <stdio.h> struct stu{ ]; int num; int age; ]; }boya[],boyb[]; struct stu *pa,*pb; mai ...

  2. [转]nginx+fastcgi+c/c++搭建高性能Web框架

    FROM : http://blog.csdn.net/marising/article/details/3932938 1.Nginx 1.1.安装 Nginx 的中文维基 http://wiki. ...

  3. SQL使用开窗函数与CTE查询每月销售额的前几名

    WITH tagTab AS( SELECT YearMonth, pm=RANK() OVER(PARTITION BY YearMonth ORDER BY amount DESC) FROM S ...

  4. Android 开发之旅:view的几种布局方式及实践

    本文的主要内容就是分别介绍以上视图的七种布局显示方式效果及实现,大纲如下: 1.View布局概述 2.线性布局(Linear Layout) 2.1.Tips:android:layout_weigh ...

  5. hadoop: hive 1.2.0 在mac机上的安装与配置

    环境:mac OS X Yosemite + hadoop 2.6.0 + hive 1.2.0 + jdk 1.7.0_79 前提:hadoop必须先安装,且处于运行状态(伪分式模式或全分布模式均可 ...

  6. string to char* and char* to string 玩转 String 和 Char*

    char 类型是c语言中常见的一个数据类型,string是c++中的一个,它的定义为 Strings are objects that represent sequences of character ...

  7. Atom插件安装

    Atom插件安装 Atom狂拽炫酷插件之activate-power-mode 引语: 在前文中提到了关于插件的安装,似乎简单易操作,不过最后我发现是我自己想简单了. activate-power-m ...

  8. QT 智能提示设置

    qt5.0的智能提示设置 qt默认的是Ctrl+空格 但这个是切换输入法,用着也不习惯 修改的地方是 工具->选项->环境 键盘选项把CompleteThis修改成自己习惯的快捷键

  9. 读懂IL代码就这么简单(二)

    一 前言 IL系列 第一篇写完后 得到高人指点,及时更正了文章中的错误,也使得我写这篇文章时更加谨慎,自己在了解相关知识点时,也更为细致.个人觉得既然做为文章写出来,就一定要保证比较高的质量,和正确率 ...

  10. STM32-外部中断,没有硬件干扰就是快乐

    一:触发方式 STM32 的外部中断是通过边沿来触发的,不支持电平触发: 二:外部中断分组 STM32 的每一个GPIO都能配置成一个外部中断触发源,STM32 通过根据引脚的序号不同将众多中断触发源 ...