【BZOJ-4386】Wycieczki DP + 矩阵乘法
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
1 2 1
2 3 2
3 4 2
4 5 1
5 3 1
4 6 3
Sample Output
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
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 + 矩阵乘法的更多相关文章
- 【bzoj2004】[Hnoi2010]Bus 公交线路 状压dp+矩阵乘法
题目描述 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计 ...
- 【bzoj3329】Xorequ 数位dp+矩阵乘法
题目描述 输入 第一行一个正整数,表示数据组数据 ,接下来T行每行一个正整数N 输出 2*T行第2*i-1行表示第i个数据中问题一的解, 第2*i行表示第i个数据中问题二的解, 样例输入 1 1 样例 ...
- 【BZOJ 3326】[Scoi2013]数数 数位dp+矩阵乘法优化
挺好的数位dp……先说一下我个人的做法:经过观察,发现这题按照以往的思路从后往前递增,不怎么好推,然后我就大胆猜想,从前往后推,发现很好推啊,维护四个变量,从开始位置到现在有了i个数 f[i]:所有数 ...
- 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,根据上面的 ...
- 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 ...
- 【BZOJ】1009: [HNOI2008]GT考试(dp+矩阵乘法+kmp+神题)
http://www.lydsy.com/JudgeOnline/problem.php?id=1009 好神的题orzzzzzzzzzz 首先我是连递推方程都想不出的人...一直想用组合来搞..看来 ...
- bzoj 4818: [Sdoi2017]序列计数【容斥原理+dp+矩阵乘法】
被空间卡的好惨啊---- 参考:http://blog.csdn.net/coldef/article/details/70305596 容斥,\( ans=ans_{没有限制}-ans{没有质数} ...
- Luogu P4643 【模板】动态dp(矩阵乘法,线段树,树链剖分)
题面 给定一棵 \(n\) 个点的树,点带点权. 有 \(m\) 次操作,每次操作给定 \(x,y\) ,表示修改点 \(x\) 的权值为 \(y\) . 你需要在每次操作之后求出这棵树的最大权独立集 ...
- LOJ.6074.[2017山东一轮集训Day6]子序列(DP 矩阵乘法)
题目链接 参考yww的题解.本来不想写来但是他有一些笔误...而且有些地方不太一样就写篇好了. 不知不觉怎么写了这么多... 另外还是有莫队做法的...(虽然可能卡不过) \(60\)分的\(O(n^ ...
随机推荐
- 在实例中说明java的类变量,成员变量和局部变量
java中一般有三种变量:类变量,成员变量和局部变量.类变量 1.下面先看类变量,看下面这个例子 public class Demo6{ public String name; public int ...
- react拷贝index.html很恶心之解决办法
https://www.npmjs.com/package/html-webpack-plugin
- 航空货运:运价类别Rate Class
1.普通货物运价(1)基础运价(代号N -注:Normal的首字母)民航总局统一规定各航段货物基础运价为45公斤以下普通货物运价.(2)重量分界点运价(代号Q -注:Quantity的首字母)国内航 ...
- python数字图像处理(16):霍夫圆和椭圆变换
在极坐标中,圆的表示方式为: x=x0+rcosθ y=y0+rsinθ 圆心为(x0,y0),r为半径,θ为旋转度数,值范围为0-359 如果给定圆心点和半径,则其它点是否在圆上,我们就能检测出来了 ...
- 手把手教你使用markdown
这是 [认真学编程] 系列的 第3篇 文章,欢迎点赞分享.写留言,这些都是对我最好的支持. 全文2300字,阅读预计5分钟] 在前面几篇文章中,多次提到装X神器markdown,本人也是markdow ...
- struts2 DMI
在使用DMI(动态方法调用)的时候要注意struts.xml配置时要把 <constant name="struts.enable.DynamicMethodInvocation&qu ...
- Qt 学习笔记 TreeWidget 增删改
在窗体上放一个TreeWidget控件和四个PushButton加一个Horizontal Spacer 布局如图 给树添加元素节点的方法和实现 .h文件 QTreeWidgetItem * AddT ...
- Webwork 学习之路【03】核心类 ServletDispatcher 的初始化
1. Webwork 与 Xwork 搭建环境需要的的jar 为:webwork-core-1.0.jar,xwork-1.0.jar,搭建webwork 需要xwork 的jar呢?原因是这样的,W ...
- 解决 未能从程序集“System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”中加载
先安装了 IIS ,再安装了 .net framework4.0 ,这样一来就要在cmd下注册.net framework4.0 步骤 第一步:修改配置文件 %windir%/system32/ine ...
- 为 Xamarin.Forms 做个跑马灯控件
前段时间,私下用 Xamarin.Forms 做了个商业项目的演示版.很多被国内App玩坏了的控件/效果,XF上都没有或是找不到对应的实现,没有办法只能亲自上阵写了几个,效果还行,就是有BUG. 这个 ...