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

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

看起来很难做 一个想法 边权递增+边的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. css怎么样设置透明度?

    css怎么样设置透明度?下面本篇文章就来给大家介绍一下使用css设置透明度的方法.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. 在CSS中想要设置透明度,可以使用opacity属性 ...

  2. 1.Unity3d的新建场景和保存场景

    Unit3d开发游戏需要使用场景.一个游戏可以有多个场景,每个场景负责一个地图或者一片区域.游戏界面的显示,因此场景非常重要. 1.File->New Scene(Ctrl+N)新建场景 2.F ...

  3. python入门008

    目录 一.for循环 作用:for循环是因为在循环取值(即遍历值)时for循环比while循环的使用更为简洁 1.for循环语法: 2.应用案例: 注意:break 与 continue也可以用于fo ...

  4. CentOS7下安装Docker《超详细新手教程》

    1.使用 root 权限登录 Centos.确保 yum 包更新到最新. sudo yum update 2.卸载旧版本(如果安装过旧版本的话) sudo yum remove docker dock ...

  5. VS插件 resharper安装破解教程

    https://masuit.com/20 ReSharper是一款由jetbrains开发的针对C#, VB.NET, ASP.NET, XML,和XAML的编辑器.沿袭了jetbrains开发工具 ...

  6. [JAVA]标准IO流操作

    import java.io.*; /** * @Description: * @projectName:JavaTest * @see:PACKAGE_NAME * @author:郑晓龙 * @c ...

  7. WPF手机号码归属批量查询并导出到Excel

    工具下载地址:https://download.csdn.net/download/m0_37137902/12589801 1WPF页面xaml代码 <Window x:Class=" ...

  8. web常用的unicode字符集

    也不知道出处

  9. java 基础(二) 搭建Java编译环境(linux系统)

    jdk安装配置 首先下载JDK和JRE,这里你的需要看看你的Linux系统是多少位的,比如我的是64位的:下载JDK并指定到Download目录,JRE同样操作:解压并且配置环境: tar -zxvf ...

  10. Python之爬虫(二十六) Scrapy登录知乎

    因为现在很多网站为了限制爬虫,设置了为只有登录才能看更多的内容,不登录只能看到部分内容,这也是一种反爬虫的手段,所以这个文章通过模拟登录知乎来作为例子,演示如何通过scrapy登录知乎 在通过scra ...