题意:

n个点,m条边,问从1走到n的最短路,其中有K次机会可以让一条路的权值变成0。
1≤N≤10000;1≤M≤500000;1≤K≤20

题解:

拆点,一个点拆成K个,分别表示到了这个点时还有多少次机会。
(x,k)-->(y,k-1),cost=0 或 (x,k)-->(y,k),cost=a[i].d;
这题数据比较大, 需要很多优化。(应该只是蒟蒻我才需要这么多优化。。)
1.不用spfa(时间复杂度不稳定),用dijkstra+优先队列优化
2.拆点不拆边。g[i]表示i这个点是由谁拆分出来的,id[i]表示i这个点表示还能用几次,st[i]表示i拆分出来的点的编号从什么开始,图就按照原图建立,比如(x,k)-->(y,k-1)就可以直接找到st[x]+k -- > st[y]+k-1。
3.如果“目标点n 用完了K次机会”这个状态到1的最短路已经算出来了,那一定是最优的,其它的都不用算了。加了这句话从10s+跑到了0.6s。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
using namespace std; typedef long long LL;
const int N=**,M=;//不知道为什么点要开两倍才能过。。。
const LL INF=(LL)1e15;
struct node{
int x,y,next;
LL d;
}a[*M];
int n,m,K,len,num,first[N],g[N],id[N],st[N];
LL dis[N],mn[N];
struct point{int x;LL d;};
struct cmp{
bool operator () (point &x,point &y){return x.d>y.d;}
};
priority_queue<point,vector<point>,cmp> q; LL minn(LL x,LL y){return x<y ? x:y;} void ins(int x,int y,LL d)
{
a[++len].x=x;a[len].y=y;a[len].d=d;
a[len].next=first[x];first[x]=len;
} void dijkstra()
{
int y,bk=;
point t;
for(int i=;i<=num;i++) dis[i]=-;
// for(int i=1;i<=num;i++) if(dis[i]!=-1) printf("%d g = %d id = %d dis = %lld\n",i,g[i],id[i],dis[i]); memset(mn,,sizeof(mn));
while(!q.empty()) q.pop();
for(int i=;i<=K;i++) dis[st[]+i]=; for(int i=first[];i;i=a[i].next)
{
for(int j=;j<=K;j++)
{
t.x=st[a[i].y]+j;
t.d=dis[st[]+j]+a[i].d;
if(mn[t.x]>t.d) mn[t.x]=t.d,q.push(t);//如果原来这个点已经可以被更优的所更新,那就不放到队列里面。
if(j>=)
{
t.x=st[a[i].y]+j-;
t.d=dis[st[]+j];
if(mn[t.x]>t.d) mn[t.x]=t.d,q.push(t);
}
}
}
while(!q.empty() && !bk)
{
while(!q.empty())
{
t=q.top();q.pop();
if(dis[t.x]==-)
{
dis[t.x]=t.d;
y=t.x;
if(y==st[n]) bk=;
//如果“目标点n 用完了K次机会”这个状态到1的最短路已经算出来了,那一定是最优的,其它的都不用算了。加了这句话从10s+跑到了0.6s。
break;
}
}
for(int i=first[g[y]];i;i=a[i].next)
{
t.x=st[a[i].y]+id[y];
t.d=dis[y]+a[i].d;
if(dis[t.x]==- && mn[t.x]>t.d) mn[t.x]=t.d,q.push(t);
if(id[y]>=)
{
t.x=st[a[i].y]+id[y]-;
t.d=dis[y];
if(dis[t.x]==- && mn[t.x]>t.d) mn[t.x]=t.d,q.push(t);
}
}
}
} int main()
{
// freopen("a.in","r",stdin);
freopen("revamp.in","r",stdin);
freopen("revamp.out","w",stdout);
scanf("%d%d%d",&n,&m,&K);
len=;num=;
memset(first,,sizeof(first));
for(int i=;i<=m;i++)
{
int x,y;LL d;
scanf("%d%d%lld",&x,&y,&d);
ins(x,y,d);
ins(y,x,d);
}
for(int i=;i<=n;i++)
for(int j=;j<=K;j++)
{
g[++num]=i,id[num]=j;
if(j==) st[i]=num;
} dijkstra();
// for(int i=1;i<=num;i++) if(dis[i]!=-1) printf("%d g = %d id = %d dis = %lld\n",i,g[i],id[i],dis[i]);
LL ans=INF;
for(int i=st[n];i<=st[n]+K;i++)
if(dis[i]!=-) ans=minn(ans,dis[i]);
printf("%lld\n",ans);
return ;
}

【bzo1579】拆点+dijkstra优先队列优化+其他优化的更多相关文章

  1. 地铁 Dijkstra(优先队列优化) 湖南省第12届省赛

    传送门:地铁 思路:拆点,最短路:拆点比较复杂,所以对边进行最短路,spfa会tle,所以改用Dijkstra(优先队列优化) 模板 /******************************** ...

  2. 晴天小猪历险记之Hill(Dijkstra优先队列优化)

    描述 这一天,他来到了一座深山的山脚下,因为只有这座深山中的一位隐者才知道这种药草的所在.但是上山的路错综复杂,由于小小猪的病情,晴天小猪想找一条需时最少的路到达山顶,但现在它一头雾水,所以向你求助. ...

  3. (模板)poj2387(dijkstra+优先队列优化模板题)

    题目链接:https://vjudge.net/problem/POJ-2387 题意:给n个点(<=1000),m条边(<=2000),求结点n到结点1的最短路. 思路:dijkstra ...

  4. dijkstra与他的优化!!!

    目录 SPFA已死,有事烧纸 Dijkstra 配对堆 引言 讲解 合并 修改 弹出堆顶pop 代码 结合! 1 2 @ SPFA已死,有事烧纸 其实我本人也是一个SPFA的忠诚用户,至少我的最少费用 ...

  5. Til the Cows Come Home 最短路Dijkstra+bellman(普通+优化)

    Til the Cows Come Home 最短路Dijkstra+bellman(普通+优化) 贝西在田里,想在农夫约翰叫醒她早上挤奶之前回到谷仓尽可能多地睡一觉.贝西需要她的美梦,所以她想尽快回 ...

  6. POJ 3268 Silver Cow Party (Dijkstra + 优先队列)

    题意:由n个牧场,编号1到n.每个牧场有一头牛.现在在牧场x举办party,每头牛都去参加,然后再回到自己的牧场.牧场之间会有一些单向的路.每头牛都会让自己往返的路程最短.问所有牛当中最长的往返路程是 ...

  7. 【poj 1724】 ROADS 最短路(dijkstra+优先队列)

    ROADS Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12436 Accepted: 4591 Description N ...

  8. spark优化之优化数据结构

    概序: 要减少内存的消耗,除了使用高效的序列化类库以外,还有一个很重要的事情,就是优化数据结构.从而避免Java语法特性中所导致的额外内存的开销,比如基于指针的Java数据结构,以及包装类型. 有一个 ...

  9. POJ 1511 - Invitation Cards (dijkstra优先队列)

    题目链接:http://poj.org/problem?id=1511 就是求从起点到其他点的最短距离加上其他点到起点的最短距离的和 , 注意路是单向的. 因为点和边很多, 所以用dijkstra优先 ...

随机推荐

  1. 软件工程 speedsnail 第二次冲刺9

    20150526 完成任务:划线的优化,速度和谐: 遇到问题: 问题1 速度仍然不满意 解决1 未解决 明日任务: 蜗牛碰到线后速度方向的调整:(做优化)

  2. CentOS基础命令

    为网卡配置静态IP地址建议通过交互式界面nmtui进行配置 firewalld和iptablesCentOS7使用firewald取代原来的iptables,但实际上底层还是iptables,在上层加 ...

  3. Android 布局方式学习

    一.LinearLayout线性布局: 线性布局是程序中最常见的一种布局方式,线性布局可以分为水平线性布局和垂直线性布局两种, 通过android:orientation属性可以设置线性布局的方向 1 ...

  4. C的强制转换和C++的强制转换(转)

    C的强制转换: (type)<expression> 其中,type为类型描述符,如int,float等.<expression>为表达式.经强制类型转换运算符运算后,返回一个 ...

  5. BZOJ4289 PA2012Tax(最短路)

    一个暴力的做法是把边看成点,之间的边权为两边的较大权值,最短路即可.但这样显然会被菊花图之类的卡掉. 考虑优化建图.将边拆成两个有向边,同样化边为点.原图中同一条边在新图中的两个点之间连边权为原边权的 ...

  6. springboot2.0 集成elasticsearch,实现检索、分页、排序

    springboot整合es的方式: transport方式(7.0弃用,8.0移除) spring-data(完全当做数据库来用,无法全部支持es,内部也是基于transport,包装后使用非常简单 ...

  7. 【刷题】BZOJ 1143 [CTSC2008]祭祀river

    Description 在遥远的东方,有一个神秘的民族,自称Y族.他们世代居住在水面上,奉龙王为神.每逢重大庆典, Y族都会在水面上举办盛大的祭祀活动.我们可以把Y族居住地水系看成一个由岔口和河道组成 ...

  8. [JSOI2010]部落划分 最小生成树

    一道最小生成树经典题 由于是最靠近的两个部落尽可能远,如果我们先处理出任意两个居住点之间的距离并将其当做边,那么我们可以发现,因为在一个部落里面的边是不用计入答案的,所以应该要尽量把小边放在一个部落里 ...

  9. BZOJ1149:[CTSC/APIO2007]风铃——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=1149 https://www.luogu.org/problemnew/show/P3621 sb ...

  10. BZOJ3343 & 洛谷2801:教主的魔法——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3343 https://www.luogu.org/problemnew/show/2801 题目描述 ...