并不对劲的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]品酒大会
传送门-> 又称普及大会. 这题没什么好说的……后缀自动机裸题……并不对劲的人太菜了,之前照着标程逐行比对才过了这道题,前几天刚刚把这题一遍写对…… 这题的输出和某两点相同后缀的长度有关,那么把 ...
随机推荐
- python3--shelve 模块
shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式 import shelve d = shelve.open('shelve_t ...
- Python 单向队列Queue模块详解
Python 单向队列Queue模块详解 单向队列Queue,先进先出 '''A multi-producer, multi-consumer queue.''' try: import thread ...
- Leetcode 227.基本计算器II
基本计算器II 实现一个基本的计算器来计算一个简单的字符串表达式的值. 字符串表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格 . 整数除法仅保留整数部分. 示例 1: 输入: " ...
- 用svn下载github中指定目录的文件
1.先用命令看看github的分支 svn ls https://github.com/BlueRiverInteractive/robovm-ios-bindings 输出: branches/ t ...
- 【BZOJ3939】Cow Hopscotch(动态开点线段树)
题意: 就像人类喜欢跳格子游戏一样,FJ的奶牛们发明了一种新的跳格子游戏.虽然这种接近一吨的笨拙的动物玩跳格子游戏几乎总是不愉快地结束,但是这并没有阻止奶牛们在每天下午参加跳格子游戏 游戏在一个R* ...
- Java有几种线程池?
Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程newFixed ...
- JAVA实验--统计文章中单词的个数并排序
分析: 1)要统计单词的个数,就自己的对文章中单词出现的判断的理解来说是:当出现一个非字母的字符的时候,对前面的一部分字符串归结为单词 2)对于最后要判断字母出现的个数这个问题,我认为应该是要用到ma ...
- INFO org.apache.hadoop.ipc.RPC: Server at master/192.168.200.128:9000 not available yet, Zzzzz...
hadoop 启动时namenode和datanode可以启动,使用jps命令也可以看到进程,但是在浏览器中输入master:50070却没有显示datanode 查看datanode的log日志: ...
- ArcGIS10.x Engine直连提示连接超时ORA-12170 来自:http://www.iarcgis.com/?p=1004
导语 随着Esri大力宣传直连,用户也越来越由服务连接,改为直连,当然ArcGIS Engine开发用户也不例外. 环境 Oracle数据库,ArcGIS版本不限,不过由于9版本多以服务连接,以10版 ...
- CentOS系统中常用查看系统信息和日志命令小结
转载:http://www.3lian.com/edu/2015/04-09/204628.html 进程 # ps -ef # 查看所有进程 # top # 实时显示进程状态(另一篇文章里面有详细的 ...