因为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. xtu read problem training 3 B - Gears

    Gears Time Limit: 2000ms Memory Limit: 65536KB This problem will be judged on ZJU. Original ID: 3789 ...

  2. 用SQLLDR来装载date类型的控制文件

    以前给山东某单位做oracle数据库恢复得时候,恢复出来得数据中包含date类型,当时给客户提供得是sqlldr得方式,因为数据量比较大,用sqlldr装载起来速度比较快,所以采用了这种方式,结果在装 ...

  3. devstack脚本安装Openstack总结(转载)

    1:vmware 基本设置 我采用的vmware workstation 8.0的版本,其他版本应该都是没问题.我是把虚拟机放在NAT的网络. 虚拟机就单块网卡就可以. 如果你希望可以在dashboa ...

  4. 【UTR #2】[UOJ#278]题目排列顺序 [UOJ#279]题目交流通道 [UOJ#280]题目难度提升

    [UOJ#278][UTR #2]题目排列顺序 试题描述 “又要出题了.” 宇宙出题中心主任 —— 吉米多出题斯基,坐在办公桌前策划即将到来的 UOI. 这场比赛有 n 道题,吉米多出题斯基需要决定这 ...

  5. Hotel(poj 3667)

    题意:询问区间最长连续空串 /* 用线段树维护区间最长连续左空串和右空串 */ #include<cstdio> #include<iostream> #define N 50 ...

  6. HDU 4651 (生成函数)

    HDU 4651 Partition Problem : n的整数划分方案数.(n <= 100008) Solution : 参考资料: 五角数 欧拉函数 五边形数定理 整数划分 一份详细的题 ...

  7. SGU 194 无源无汇可行流求解

    题意:n个点,m条边,每条边有容量限制 l--c,每个点满足容量平衡(流入等于流出),求可行解 无源无汇可行流问题,建立以一个超级源点和超级汇点,由于原来最大流问题时候,流量下界其实为0, 所以要转化 ...

  8. poj1459多源多汇最大流问题

    /*基本构图题,多源多汇,添加一个源点和一个汇点,所有源点都来自这个源点,同理,所有汇点 都汇于这个汇点,dinic第二战,本来应该1A的,犯了一个低级错误!while(scanf("%d) ...

  9. iOS present出一个背景为半透明的试图

    WDKChatRoomViewController *roomVC = [[WDKChatRoomViewController alloc] init]; roomVC.titleStr = [gro ...

  10. ZOJ 3471 【状态压缩DP】

    题意: 有n种化学物质,他们彼此反应会有一种消失并释放出能量. 给出矩阵,第i行j列代表i和j反应j消失释放的能量. 求最大释放多少能量. 思路: 状态压缩DP,我是这么想的. 利用二进制0代表该物质 ...