因为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的更多相关文章

  1. 并不对劲的BJOI2019

    一些感想 现实并非游戏,并不支持反复刷关 猎人和防御工事一起被老山龙摧毁了: 猎人惨死雨中,结云村永无放晴之日: 猎人被狂龙病毒侵蚀,天空山上黑蚀龙泛滥. 好像这才是怪物猎人系列的真实结局呢 day ...

  2. 并不对劲的uoj276. [清华集训2016]汽水

    想要很对劲的讲解,请点击这里 题目大意 有一棵\(n\)(\(n\leq 50000\))个节点的树,有边权 求一条路径使该路径的边权平均值最接近给出的一个数\(k\) 输出边权平均值下取整的整数部分 ...

  3. 并不对劲的DFT

    FFT是一个很多人选择背诵全文的算法. #include<algorithm> #include<cmath> #include<complex> #include ...

  4. 并不对劲的字符串专题(三):Trie树

    据说这些并不对劲的内容是<信息学奥赛一本通提高篇>的配套练习. 并不会讲Trie树. 1.poj1056-> 模板题. 2.bzoj1212-> 设dp[i]表示T长度为i的前 ...

  5. 并不对劲的字符串专题(二):kmp

    据说这些并不对劲的内容是<信息学奥赛一本通提高篇>的配套练习. 先感叹一句<信息学奥赛一本通提高篇>上对kmp的解释和matrix67的博客相似度99%(还抄错了),莫非mat ...

  6. 并不对劲的bzoj1861: [Zjoi2006]Book 书架

    传送门-> 这题的正确做法是splay维护这摞书. 但是并不对劲的人选择了暴力(皮这一下很开心). #include<algorithm> #include<cmath> ...

  7. 并不对劲的bzoj3932: [CQOI2015]任务查询系统

    传送门-> 离线操作听上去很简单,遗憾的是它强制在线. 每个时刻可以看成可持久化线段树中的一个版本,而每一个版本的线段树维护的是值某一段区间且在这个版本对应的时刻出现的数之和. 会发现同一时刻可 ...

  8. 并不对劲的bzoj1853:[SCOI2010]幸运数字

    传送门-> 据说本题的正确读法是[shìng运数字]. 听上去本题很适合暴力,于是并不对劲的人就去写了.其实这题就是一个很普(有)通(趣)暴力+神奇的优化. 首先,会发现幸运数字很少,那么就先搜 ...

  9. 并不对劲的bzoj4199: [Noi2015]品酒大会

    传送门-> 又称普及大会. 这题没什么好说的……后缀自动机裸题……并不对劲的人太菜了,之前照着标程逐行比对才过了这道题,前几天刚刚把这题一遍写对…… 这题的输出和某两点相同后缀的长度有关,那么把 ...

随机推荐

  1. 相应缓存设置HttpCacheability 枚举

      成员名称 说明   NoCache 设置 Cache-Control: no-cache 标头.如果没有字段名,则指令应用于整个请求,且在满足请求前,共享(代理服务器)缓存必须对原始 Web 服务 ...

  2. UITableView点击背景

    系统自定义的点击背景有时间觉得效果不好想换个 - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelect ...

  3. HDU 1874 最直接的最短路径问题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1874 Problem Description 某省自从实行了很多年的畅通工程计划后,终于修建了很多路. ...

  4. PHP统计目录中文件个数和文件大小

    <meta charset="utf-8"><?php $dirn = 0; //目录数 $filen = 0; //文件数 //用来统计一个目录下的文件和目录的 ...

  5. loadrunner 多用户并发操作解读

    假设存在: 数据:A.B.C 虚拟用户:Vuser1.Vuser2.Vuser3 脚本中参数出现三次,脚本迭代三次 怎样取下一行数据? Sequential:顺序,所有虚拟用户按照顺序读取数据表 Ra ...

  6. UINavigationController 小记

    1.以栈的形式管理视图控制器,push 和 pop 方法来弹入和弹出控制器,最多只能显示一个视图控制器. 2.使用pop方法可以移除栈顶控制器,当一个控制器被pop后,控制器内存会被释放了. 3.一层 ...

  7. poj——3118 Arbiter

      Arbiter 题目描述:      “仲裁者”是<星际争霸>科幻系列中的一种太空船.仲裁者级太空船是神族的战船,专门提供精神力支援.不像其他战船的人员主要是战士阶级,仲裁者所承载的都 ...

  8. union关键字和字节大小端序的确定

    union 关键字的用法与struct 的用法非常类似. union 维护足够的空间来置放多个数据成员中的“一种”,而不是为每一个数据成员配置空间,在union 中所有的数据成员共用一个空间,同一时间 ...

  9. TDBXJSONStream(BERLIN新增)的使用

    DELPHI 10.1 BERLIN新增TDBXJSONStream类,用于方便地将数据序列为JSON,和将JSON还原出来数据. DATASNAP远程方法也相应地增加了支持返回TDBXJSONStr ...

  10. jmeter的master远程运行和停止slave

    jmeter可以部署成master-slave或者叫client-server模式,一个master(client)可以同时控制多个slave(server). 在linux系统下,master(cl ...