并不对劲的noip2017d1t3
因为A掉了d1t1,十分开心,把d1t3的代码调出来了。
一般情况下,noip每一天总有一道dp题,然而d1前两道题都不是,再看看第三题的数据范围,就能大概猜出是dp了。
这道题和最短路计数看上去很像。回想一下最短路计数的解法,大概是按照bfs序进行dp,dp[u]表示到节点u的条数。对于这道题而言,求的不是最短路条数而是长度不超过最短路+k的路径条数,那么就可以用dp[u][j]表示到节点u路径长度等于j的路径数。
至于如何转移,用dis[x]表示x到1的最短路长度,则当dis[u]+w[k]+j-dis[x]<=k有dp[x][dis[u]+w[k]+j-dis[vv]]+=dp[u][j]。
至于转移顺序,想到最短路计数是bfs序,而这道题有边权,那么就是dijkstra序(<-瞎编的词),其实就是dis[x]由小到大的顺序。
至于0边,需要建一个新图,图中只有0边。用一个拓扑排序找出0环,若环上存在点x满足1到x的距离+x到n的距离<=1到n的距离+k,则这个环会被计数,输出-1。还有一点需要注意的是,当出现0边时,dp顺序不单单是dis[x]的顺序。当出现x--0-->y,显然是要先算dp[x]的。这是就需要用到之前算出的拓扑序,当两个点的dis相等时,先算拓扑序靠前的那个。
下面是代码,我略作修改,使它有可能RE。
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define stnd struct node
#define nd node
#define oops operator
#define maxn 400010
#define maxm 800010
#define ll long long
using namespace std;
ll v[maxm],w[maxm],fir[maxn],nxt[maxm],cnt;//For roads.
ll fv[maxm],fw[maxm],ffir[maxn],fnxt[maxm],fcnt;//For froads.
ll tl,in[maxn],dep[maxn],ord[maxn],inq[maxn];//For topo sorting.
ll n,m,inf,t,dp[maxn][],kkk,p;;//For counting.
ll dis[maxn],fdis[maxn];//For dijkstra.
bool fl,vis[maxn][];
stnd
{
ll x,y;
bool oops <(const nd &zz)const
{
return y>zz.y;
}
};
inline ll read()
{
ll xx=,ff=;
char ch=getchar();
while(isdigit(ch)== && ch!='-')ch=getchar();
if(ch=='-')ff=-,ch=getchar();
while(isdigit(ch))xx=xx*+ch-'',ch=getchar();
return xx*ff;
}
void addedge(ll u1,ll v1,ll w1)
{
v[cnt]=v1,w[cnt]=w1,nxt[cnt]=fir[u1],fir[u1]=cnt++;
fv[fcnt]=u1,fw[fcnt]=w1,fnxt[fcnt]=ffir[v1],ffir[v1]=fcnt++;
}
void dj()
{
memset(dis,0x7f,sizeof(dis));
priority_queue<stnd>q;
stnd tmp;
tmp.x=,tmp.y=;
dis[]=;
q.push(tmp);
while(!q.empty())
{
ll u=q.top().x,du=q.top().y;q.pop();
if(dis[u]<du)continue;
for(ll k=fir[u];k!=-;k=nxt[k])
{
ll vv=v[k];
if(dis[vv]>dis[u]+w[k])
{
dis[vv]=dis[u]+w[k];
tmp.x=vv,tmp.y=dis[vv];
q.push(tmp);
}
}
}
}
void fdj()
{
memset(fdis,0x7f,sizeof(fdis));
priority_queue<stnd>q;
stnd tmp;
tmp.x=n,tmp.y=;
fdis[n]=;
q.push(tmp);
while(!q.empty())
{
ll u=q.top().x,du=q.top().y;q.pop();
if(fdis[u]<du)continue;
for(ll k=ffir[u];k!=-;k=fnxt[k])
{
ll vv=fv[k];
if(fdis[vv]>fdis[u]+fw[k])
{
fdis[vv]=fdis[u]+fw[k];
tmp.x=vv,tmp.y=fdis[vv];
q.push(tmp);
}
}
}
}
void topoo(ll xx)
{
inq[xx]=;
ord[tl++]=xx;
for(ll k=fir[xx];k!=-;k=nxt[k])
{
if(w[k]!=)continue;
ll vv=v[k];
in[vv]--;
if(in[vv]==)
topoo(vv);
}
return;
}
void topo()
{
tl=;
memset(inq,,sizeof(inq));
memset(in,,sizeof(in));
for(ll i=;i<m;i++)
if(w[i]==)in[v[i]]++;
for(ll i=;i<=n;i++)
if(inq[i]== && in[i]==)
topoo(i);
for(ll i=;i<=n;i++)
{
if(in[i]!= &&
dis[i]+fdis[i]<=dis[n]+kkk)
fl=;
}
}
bool dfs(int u,int j)
{
if(vis[u][j])return ;
if(~dp[u][j])return ;
vis[u][j]=;
if(u==n)dp[u][j]=;
else dp[u][j]=;
for(int k=fir[u];k!=-;k=nxt[k])
{
int vv=v[k],tt=dis[u]-dis[vv]+w[k]+j;
if(tt<=kkk &&
dis[u]+j+w[k]+fdis[vv]<=kkk+fdis[])
{
if(dfs(vv,tt))return ;
dp[u][j]+=dp[vv][tt];
dp[u][j]%=p;
}
}
vis[u][j]=;
return ;
}
int main()
{
t=read();
while(t--)
{
cnt=fcnt=fl=;
n=read(),m=read(),kkk=read(),p=read();
memset(fir,-,sizeof(fir));
memset(ffir,-,sizeof(ffir));
memset(dp,-,sizeof(dp));
memset(vis,,sizeof(vis));
for(ll i=;i<=m;i++)
{
ll x=read(),y=read(),z=read();
addedge(x,y,z);
}
dj();
fdj();
topo();
if(fl)cout<<-;
else
{
dfs(,);
cout<<dp[][];
}
cout<<endl;
}
return ;
}
并不对劲的noip2017d1t3的更多相关文章
- 并不对劲的BJOI2019
一些感想 现实并非游戏,并不支持反复刷关 猎人和防御工事一起被老山龙摧毁了: 猎人惨死雨中,结云村永无放晴之日: 猎人被狂龙病毒侵蚀,天空山上黑蚀龙泛滥. 好像这才是怪物猎人系列的真实结局呢 day ...
- 并不对劲的uoj276. [清华集训2016]汽水
想要很对劲的讲解,请点击这里 题目大意 有一棵\(n\)(\(n\leq 50000\))个节点的树,有边权 求一条路径使该路径的边权平均值最接近给出的一个数\(k\) 输出边权平均值下取整的整数部分 ...
- 并不对劲的DFT
FFT是一个很多人选择背诵全文的算法. #include<algorithm> #include<cmath> #include<complex> #include ...
- 并不对劲的字符串专题(三):Trie树
据说这些并不对劲的内容是<信息学奥赛一本通提高篇>的配套练习. 并不会讲Trie树. 1.poj1056-> 模板题. 2.bzoj1212-> 设dp[i]表示T长度为i的前 ...
- 并不对劲的字符串专题(二):kmp
据说这些并不对劲的内容是<信息学奥赛一本通提高篇>的配套练习. 先感叹一句<信息学奥赛一本通提高篇>上对kmp的解释和matrix67的博客相似度99%(还抄错了),莫非mat ...
- 并不对劲的bzoj1861: [Zjoi2006]Book 书架
传送门-> 这题的正确做法是splay维护这摞书. 但是并不对劲的人选择了暴力(皮这一下很开心). #include<algorithm> #include<cmath> ...
- 并不对劲的bzoj3932: [CQOI2015]任务查询系统
传送门-> 离线操作听上去很简单,遗憾的是它强制在线. 每个时刻可以看成可持久化线段树中的一个版本,而每一个版本的线段树维护的是值某一段区间且在这个版本对应的时刻出现的数之和. 会发现同一时刻可 ...
- 并不对劲的bzoj1853:[SCOI2010]幸运数字
传送门-> 据说本题的正确读法是[shìng运数字]. 听上去本题很适合暴力,于是并不对劲的人就去写了.其实这题就是一个很普(有)通(趣)暴力+神奇的优化. 首先,会发现幸运数字很少,那么就先搜 ...
- 并不对劲的bzoj4199: [Noi2015]品酒大会
传送门-> 又称普及大会. 这题没什么好说的……后缀自动机裸题……并不对劲的人太菜了,之前照着标程逐行比对才过了这道题,前几天刚刚把这题一遍写对…… 这题的输出和某两点相同后缀的长度有关,那么把 ...
随机推荐
- PTA 04-树6 Complete Binary Search Tree (30分)
题目地址 https://pta.patest.cn/pta/test/16/exam/4/question/669 5-7 Complete Binary Search Tree (30分) A ...
- [转]SQL SERVER数据库还原的方法
SQL SERVER数据库还原的方法 在SQL SERVER 2005下还原数据库 1.新建数据库A,右键还原数据库,此时目标数据库为A,选择备份 文件B_db_201311040200.BAK,还原 ...
- linux下mysql登录报错“Access denied for user 'root'@'localhost' (using password: YES”)的处理方法
最近登录某台服务器的mysql时候总报错: Access[root@log01 ~]# mysql -u root -p Enter password: ERROR 1045 (28000): Acc ...
- 深入理解计算机操作系统——12章:多进程,IO多路复用
三种并行的应用程序: 1. 基于进程的并发编程: 2. 基于IO多路复用的并发: 3. 基于线程的并发编程: 12.1 基于进程的并发编程 进程的优劣: (1)进程间共享文件表,但不共享用户地址空间, ...
- 转 Python 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)
转自: http://www.cnblogs.com/huangcong/archive/2011/08/29/2158268.html 黄聪:Python 字符串操作(string替换.删除.截取. ...
- php的错误控制运算符
php的错误控制运算符 PHP中提供了一个错误控制运算符“@”. 可以将@放置在一个PHP表达式之前,该表达式可能产生的任何错误信息都被忽略掉: 如果开启了php.ini 中的 track_error ...
- js正则匹配身份证号 有坑
// 不能加g,每次匹配会以lastIndex为起始位去查找 // 若加g,匹配到会用最后一位的index去改变lastIndex,没有匹配到则会把lastIndex重置为0 // 不加g,lastI ...
- Java操作XML牛逼利器JDOM&DOM4J
JDOM JDOM 是一种使用 XML(标准通用标记语言下的一个子集) 的独特 Java 工具包,用于快速开发 XML 应用 程序. JDOM 官方网站:http://www.jdom.org/ 利 ...
- ARM PPC 交叉编译环境搭建
ARM: 1,下载cross-3.4.1.tar.bz2 2,在/usr/local目录下建立arm目录 3,将cross-3.4.1.tar.bz2拷贝到arm目录下 4,tar jxvf cros ...
- 从头开始学Android之(一)——— Android架构
从事Android开发已经两年多了,最近项目上特别清闲,刚开始时在闲暇的时候都不知道干嘛,整天混日子.有一天突然有个以前同学找到我,说要我帮忙做一个Android的需求,就是在后台截屏(涉及到服务以及 ...