博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[NOIP2017]逛公园
阅读量:6089 次
发布时间:2019-06-20

本文共 4655 字,大约阅读时间需要 15 分钟。

2018-05-24

题目大意:

给一张由非负边组成的图,(可能有零边),设从出发点1到终点n的路径的最短路为d,求出所有到达n的路径中,路程长度为d~d+k的方案总数。(取模)

若有无数条,输出-1;

分析:

暴力:

1.30分k=0,最短路计数暴力妥妥30分

2.70分,因为,k<=50,比较小,而n<=100000,所以是NK复杂度。

每个点的偏移量k可以由之前能到达这个点的小于等于k的值转过来,

所以设f[i][j]表示,在第i号点,距离到i号点最短路的偏移量为j的方案总数。也就是说,到i的路径长度为dis[i]+j的方案数。(dis[i]为从1到i最短路长度)

其中,j>=0&&j<=k

可以知道,从1-u-v和从1-v(路径都是最短路)相比较,偏移量就是:dis[u]+val[u,v]+j-dis[x]这么长

发现,同一层之间可能有转移。

不能有后效性,那么转移顺序怎么处理?

发现,同一层之间有转移的话,必然是从dis小的到dis大的。

dis大的不可能转移到dis小的,并且偏移量不变。

所以对dis排序。

至于dis相同的,也不可能之间产生转移。随便排序就好了。

 

100分

但是刚才这个办法显然有坑。剩下的数据点,有0边。

先判断-1,发现,有0环,并且走0环可以是一条符合长度偏移量<=k的方案。

(但是我蒟蒻,没想这么多,直接判的零环,没想到过了。看来没有“有零环但不在方案数中”的测试点)

(所以代码其实有错,正解应该是判断0环上的是否存在一点x符合 dis1[x]+disn[x]<=dis[n]+k 这里,dis1表示从1出发最短路,disn表示从n出发最短路)

(这样才能保证走到0环后,随便走零边都是一种合法方案。而不是还没到0环就超过了k)

对于0链,a->b->c,w均为0,dis值是一样的,不能按dis值随便排了,必须先更新a,再b,再c。

所以,拓扑排序。专为0边准备。

把所有0边揪出来,判断-1的时候,也就进行了拓扑排序。

所以,现在,结点排序的优先级定义为:dis不同,dis小的优,否则拓扑序小的优。

spfa最短路。(有人用线段树,我太弱不会)

这个题,不开O2,洛谷还是要T两个点。很差。

但是换了LibreOJ就2000ms一个点AC了。看来luogu评测机还是比较慢。

估计CCF老爷机要卡爆了。就算考试想出正解,估计也就卡到70分了。

总结:spfa+拓扑+dp+卡常

代码:

#include
#define num ch-'0'using namespace std;typedef long long ll;const int N=100000+10;const int M=200000+10;const int inf=(0x3f3f3f3f)*2;int n,m,K,p;int rd(){ int x=0;char ch; while(!isdigit(ch=getchar())); for(x=num;isdigit(ch=getchar());x=x*10+num); return x;}struct node{ int nxt,to,val;}bian[M];struct zero{ int nxt,to;}e0[M];int has[N],tot;int hd[N],cnt1;//真正边 int pp[N],cnt3;//0边 int du[N];//度数 int dis[N];//最短路 int da[N];//最终的循环顺序da[i]表示排名为i的节点 int q[N*2],l,r;bool vis[N];bool flag=true;//零环bool ll f[N][52];//dp数组 int id[N];//拓扑序,主要是针对0边处理 void add1(int x,int y,int z){ bian[++cnt1].nxt=hd[x]; bian[cnt1].to=y; bian[cnt1].val=z; hd[x]=cnt1;}void add3(int x,int y)//建0边 { e0[++cnt3].nxt=pp[x]; e0[cnt3].to=y; pp[x]=cnt3;}bool jud()//判零环,这其实是错的。{ memset(vis,0,sizeof vis); l=1;r=0; for(int i=1;i<=n;i++) { if(du[i]==0) q[++r]=i; } while(l<=r) { int x=q[l++]; vis[x]=1; for(int i=pp[x];i;i=e0[i].nxt) { int y=e0[i].to; du[y]--; if(du[y]==0) q[++r]=y; } } for(int i=1;i<=n;i++) id[q[i]]=i; for(int i=1;i<=tot;i++) { if(vis[has[i]]!=1) return true; } return false;}void spfa()//最短路 { memset(vis,0,sizeof vis); for(int i=1;i<=n;i++) dis[i]=inf; dis[1]=0; vis[1]=1; l=1;r=0; q[++r]=1; while(l<=r) { int now=q[l++]; vis[now]=0; for(int i=hd[now];i;i=bian[i].nxt) { int y=bian[i].to; if(dis[y]>dis[now]+bian[i].val) { dis[y]=dis[now]+bian[i].val; if(!vis[y]) { vis[y]=1; q[++r]=y; } } } }}bool cmp(int x,int y){
//排序,决定循环顺序 return dis[x]==dis[y]?id[x]
View Code

 

 upda:2018.11.5

之前太菜了。

这个代码可以不卡常直接AC:

#include
#define reg register int#define il inline#define numb (ch^'0')using namespace std;typedef long long ll;const int N=100000+5;const int M=200000+5;int n,m,t;int k,mod;void rd(int &x){ char ch;x=0; while(!isdigit(ch=getchar())); for(x=numb;isdigit(ch=getchar());x=x*10+numb);}struct node{ int nxt,to; int val;}e[2*M],bian[2*M];int hd[N],cnt1;int pre[N],cnt2;bool in[N];int du[N];int f[N][55];int d[N];int po[N];bool zero[N];bool vis[N];void add(int x,int y,int z){ e[++cnt1].nxt=hd[x]; e[cnt1].to=y; e[cnt1].val=z; hd[x]=cnt1;}void add_c(int x,int y){ bian[++cnt2].nxt=pre[x]; bian[cnt2].to=y; pre[x]=cnt2;}int dis[N];int q[10*N],l,r;void spfa(){ l=1,r=0; memset(vis,0,sizeof vis); memset(dis,0x3f,sizeof dis); dis[1]=0;// f[1][0]=1; q[++r]=1; while(l<=r){ int x=q[l++];vis[x]=0; // cout<<" x "<
<<" dis "<
<
dis[x]+e[i].val){ dis[y]=dis[x]+e[i].val; //f[y][0]=f[x][0]; if(!vis[y]){ vis[y]=1; q[++r]=y; } } } }}bool topo(){ l=1,r=0; memset(po,0x3f,sizeof po); memset(in,0,sizeof in); for(reg i=1;i<=n;++i){ d[i]=i; if(zero[i]&&du[i]==0){ q[++r]=i; } } int lp=0; while(l<=r){ int x=q[l++]; po[x]=++lp; // cout<<" xxx "<
<
=mod)?f[y][to]+f[x][o]-mod:f[y][to]+f[x][o]; } } } } ll ans=0; for(reg i=0;i<=k;++i){ ans=ans+f[n][i]; if(ans>=mod) ans-=mod; } printf("%lld\n",ans); } return 0;}

 

转载于:https://www.cnblogs.com/Miracevin/p/9079401.html

你可能感兴趣的文章
centos使用docker下安装mysql并配置、nginx
查看>>
需要学的东西
查看>>
Linux 获取文件夹下的所有文件
查看>>
对 Sea.js 进行配置(一) seajs.config
查看>>
第六周
查看>>
解释一下 P/NP/NP-Complete/NP-Hard 等问题
查看>>
javafx for android or ios ?
查看>>
微软职位内部推荐-Senior Software Engineer II-Sharepoint
查看>>
sql 字符串操作
查看>>
【转】Android布局优化之ViewStub
查看>>
网络安全管理技术作业-SNMP实验报告
查看>>
根据Uri获取文件的绝对路径
查看>>
Flutter 插件开发:以微信SDK为例
查看>>
.NET[C#]中NullReferenceException(未将对象引用到实例)是什么问题?如何修复处理?...
查看>>
边缘控制平面Ambassador全解读
查看>>
Windows Phone 7 利用计时器DispatcherTimer创建时钟
查看>>
程序员最喜爱的12个Android应用开发框架二(转)
查看>>
vim学习与理解
查看>>
DIRECTSHOW在VS2005中PVOID64问题和配置问题
查看>>
MapReduce的模式,算法以及用例
查看>>