这是一道非常垃圾的题目 且 数据范围简直迷惑选手。。

可以发现 题目中有 边权递增 边的条数 所有边权值不同 最小边权和等条件。

看起来很难做 一个想法 边权递增+边的1的权值都不相同可以想到 关系存在于边的话应该是一张DAG.

所以 可以把边化点建图 暴力建图是\(n^2\)的 采用归并排序+前缀和优化建图就是线性的了。

然后考虑在这张DAG上搞事情 发现边的条数很难做。

怎么做都需要一个dp数组\(f_{i,j}\)表示到达i此时经过的路径数为j的最小权值。

状态数很多 尽管转移可以拓扑排序 那么总复杂度为\(Qnm\)过不了

尽管建立除了DAG但是边的条数还是很难解决。

容易想到状态\(f_{i,j,k}\)表示i到j经过k条边的最小值。

这道题迷惑的一点是 这个状态是\(1e8\) 我以为过不了所以就一直在研究怎么在DAG上做。。

其实这个状态在开\(o2\)的情况下表现非常优秀 可以通过。

根据这道题启示我以后\(1e8~2e8\)的复杂度 大胆莽。

考虑转移 由于要求边权要求递增所以可以一条边一条边往里面插入。

实际上只需要更新以这条路径为终点即可。复杂度\(mn^2\)

但是这道题数据还是很良心的 我在DAG上跑dfs就有90了。

code bf:
//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-8
#define sq sqrt
#define mod 998244353
#define S second
#define F first
#define op(x) t[x].op
#define d(x) t[x].d
#define Set(a,v) memset(a,v,sizeof(a))
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
const int MAXN=5010<<1,maxn=155;
int n,m,len,Q,id,mark,ans;
int s[MAXN],c[MAXN];
int lin[MAXN],ver[MAXN],nex[MAXN];
vector<pii>g[maxn],w[maxn];
struct wy{int x,y;int id;}t[MAXN];
inline void add(int x,int y)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
}
inline void dfs(int x,int res,int v)
{
if(v>=ans)return;
if(t[x].y==mark){ans=v;return;}
if(!res)return;
for(int i=lin[x];i;i=nex[i])dfs(ver[i],res-s[ver[i]],v+c[ver[i]]);
}
int main()
{
freopen("ha.in","r",stdin);
freopen("ha.out","w",stdout);
get(n);get(m);get(Q);
rep(1,m,i)
{
int get(x),get(y),get(z);
t[i]=(wy){x,y,z};
g[x].pb(mk(z,i));//起点.
w[y].pb(mk(z,i));//终点.
s[i]=1;c[i]=z;
}
id=m;
//以边化点.
rep(1,n,i)
{
sort(g[i].begin(),g[i].end());
sort(w[i].begin(),w[i].end());
//归并建图.
int k1=g[i].size()-1;
int k2=w[i].size()-1;
++id;
for(int k=1;k<=(int)(g[i].size()+w[i].size());++k)
{
if(k1==-1)
{
add(w[i][k2].S,id);
--k2;continue;
}
if(k2==-1){--k1;continue;}
if(w[i][k2].F<g[i][k1].F)add(id,g[i][k1].S),--k1;
else
{
add(w[i][k2].S,id);
++id;add(id,id-1);--k2;
}
}
}
rep(1,Q,i)
{
int get(a),get(b),get(C);
if(a==b){puts("0");continue;}
if(!C){puts("-1");continue;}
ans=INF;mark=b;
vep(0,g[a].size(),j)dfs(g[a][j].S,C-1,c[g[a][j].S]);
put(ans==INF?-1:ans);
}
return 0;
}
code sol:
//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-8
#define sq sqrt
#define mod 998244353
#define S second
#define F first
#define op(x) t[x].op
#define d(x) t[x].d
#define Set(a,v) memset(a,v,sizeof(a))
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
const int MAXN=5010,maxn=155;
int n,m,len,Q,id,mark,ans;
struct wy{int x,y,z;}t[MAXN];
int f[maxn][maxn][maxn];//f[i][j][k]表示由i到j经过了<=k条边的最短路.
inline int cmp(wy a,wy b){return a.z<b.z;}
int main()
{
freopen("1.in","r",stdin);
//freopen("2.out","w",stdout);
get(n);get(m);get(Q);
rep(1,m,i)
{
int get(x),get(y),get(z);
t[i]=(wy){x,y,z};
}
memset(f,0x3f,sizeof(f));
sort(t+1,t+1+m,cmp);
rep(1,n,i)rep(0,n,k)f[i][i][k]=0;
rep(1,m,j)
{
rep(1,n,i)
{
rep(1,n,k)
{
f[i][t[j].y][k]=min(f[i][t[j].y][k],f[i][t[j].x][k-1]+t[j].z);
}
}
}
rep(1,Q,i)
{
int get(x),get(y),get(z);
put(f[x][y][min(z,n)]>=INF?-1:f[x][y][min(z,n)]);
}
return 0;
}

7.1 NOI模拟赛 dp floyd的更多相关文章

  1. 6.28 NOI模拟赛 好题 状压dp 随机化

    算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...

  2. NOI模拟赛 Day1

    [考完试不想说话系列] 他们都会做呢QAQ 我毛线也不会呢QAQ 悲伤ING 考试问题: 1.感觉不是很清醒,有点困╯﹏╰ 2.为啥总不按照计划来!!! 3.脑洞在哪里 4.把模拟赛当作真正的比赛,紧 ...

  3. 7.12 NOI模拟赛 生成树 装压dp vector装压

    LINK:生成树 这场比赛我打的真失败 T3是比较容易的 却一直刚 那道"数论" 10分其实搜一下全排列. 30分容易想到对边进行装压dp. 不过存在一些细节 可以对于一个连通块的 ...

  4. 7.12 NOI模拟赛 探险队 期望 博弈 dp 最坏情况下最优策略 可并堆

    LINK:探险队 非常难的题目 考试的时候爆零了 完全没有想到到到底怎么做 (当时去刚一道数论题了. 首先考虑清楚一件事情 就是当前是知道整张地图的样子 但是不清楚到底哪条边断了. 所以我们要做的其实 ...

  5. 7.11 NOI模拟赛 graph 生成函数 dp 多项式

    LINK:graph HDU题库里的原题 没做过自闭. 考虑dp 设\(f_{i,j}\)表示前i个点构成j个联通块是树的方案数. 对于一次询问答案即为\(\sum_{j}f_{n,j}j^k\) 考 ...

  6. 7.1 NOI模拟赛 凸包套凸包 floyd 计算几何

    计算几何之所以难学 就是因为太抽象了 不够直观 而且情况很多 很繁琐 甚至有一些东西不清不楚.. 这道题注意到题目中的描述 一个鸽子在两个点所连直线上也算. 通过看题解 发现这个地方并非直线而是线段 ...

  7. 7.9 NOI模拟赛 C.走路 背包 dp 特异性

    (啊啊啊 什么考试的时候突然降智这题目硬生生没想出来. 容易发现是先走到某个地方 然后再走回来的 然后在倒着走的路径上选择一些点使得最后的得到的最多. 设\(f_{i,j}\)表示到达i这个点选择的价 ...

  8. 7.1 NOI模拟赛 计数问题 dp

    还是可以想出来的题目 不过考场上没有想出来 要 引以为戒. 初看觉得有点不可做 10分给到了爆搜. 考虑第一个特殊情况 B排列为1~m. 容易发现A排列中前m个数字 他们之间不能产生交换 且 第k个数 ...

  9. NOI 模拟赛 #2

    得分非常惨惨,半个小时写的纯暴力 70 分竟然拿了 rank 1... 如果 OYJason 和 wxjor 在可能会被爆踩吧 嘤 T1 欧拉子图 给一个无向图,如果一个边集的导出子图是一个欧拉回路, ...

随机推荐

  1. 线性dp—奶牛渡河

    题目 Farmer John以及他的N(1 <= N <= 2,500)头奶牛打算过一条河,但他们所有的渡河工具,仅仅是一个木筏. 由于奶牛不会划船,在整个渡河过程中,FJ必须始终在木筏上 ...

  2. NIVIDIA Tegra K1 QWT安装使用问题和解决办法

    在Linux系统下,Tegra K1(ARM体系),只有QtCreator的环境下,去安装Qwt6.1.0: 下载: 系统安装好之后,直接联网在系统自带的软件安装程序中搜索Qt,安装Qt5.2.1,之 ...

  3. 发布.net core Web到CentOS7

    1.发布一个.net core(只安装了.Net Core运行时,而没有安装ASP.NET Core运行时,需要添加以下节点再发布).  <PublishWithAspNetCoreTarget ...

  4. C# DataTable与Excel读取与导出

    /// <summary> /// Excel->DataTable /// </summary> /// <param name="filePath&q ...

  5. java 面向对象(十二):面向对象的特征二:继承性 (一) 前言

    1.为什么要有类的继承性?(继承性的好处) * ① 减少了代码的冗余,提高了代码的复用性 * ② 便于功能的扩展 * ③ 为之后多态性的使用,提供了前提图示: 2.继承性的格式:class A ext ...

  6. Python模块04/包/logging日志

    Python模块04/包/logging日志 目录 Python模块04/包/logging日志 内容大纲 1.包 2.logging日志 3.今日总结 内容大纲 1.包 2.logging日志 1. ...

  7. OSCP Learning Notes - Overview

    Prerequisites: Knowledge of scripting languages(Bash/Pyhon) Understanding of basic networking concep ...

  8. CSS栅格布局

    CSS栅格布局 认识栅格布局 CSS的栅格布局也被称为网格布局(Grid Layout),它是一种新兴的布局方式. 栅格布局是一个二维系统,这意味着它可以同时处理列和行,与弹性布局相似,栅格系统也是由 ...

  9. View Animation 运行原理解析

    Android 平台目前提供了两大类动画,在 Android 3.0 之前,一大类是 View Animation,包括 Tween animation(补间动画),Frame animation(帧 ...

  10. Element 季度选择器+导入

    苦恼于element没有季度选择器,网上搜罗后整理实现,以便后期开发使用 同文件夹下新建一个vue界面,命名为Quarter.vue <template> <el-form> ...