题意:

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. 软件工程课堂作业(五)——终极版随机产生四则运算题目(C++)

    一.升级要求:让程序能接受用户输入答案,并判定对错.最后给出总共对/错的数量. 二.设计思想: 1.首先输入答案并判断对错.我想到的是定义两个数组,一个存放用户算的结果,另一个存放正确答案.每输出一道 ...

  2. oracle数据库中常见的操作语句(一)

    一 创建表空间 create tablespace lfdc_data logging datafile 'D:\Database\lfdc_data.dbf' size 50m autoextend ...

  3. <Android>资源的访问,颜色、字符串、尺寸、XML、DRAWABLES资源分使用

    1.资源的访问 代码中使用Context的getResources()方法得到Resources对象,访问自己定义的资源R.资源文件类型.资源文件名称,访问系统定义的资源android.R. 资源文件 ...

  4. Swagger Authorization:bearer <token>

    1.添加如下代码 /** * * @SWG\SecurityScheme( * securityDefinition="Bearer", * type="apiKey&q ...

  5. 在ios 上 按钮 disabled 样式显示异常

    将input,button或textarea设置为disabled后,在iphone手机上样式将被覆写-webkit-appearance:none; 文字的颜色还是灰色. 原本在android 上 ...

  6. HUAS 1483 mex(离线+线段树)

    实在是太弱了.... 考虑离线,从mex[l,r]向mex[l,r+1]转移,显然是没啥东西可以记录的... 从mex[l,r]向mex[l+1,r]转移,记x=mex[l,r],如果[l+1,r]不 ...

  7. 完全理解Python的 '==' 和 'is'

    '==' 比较的是两个对象的值 'is' 比较的是两个对象的内存地址(id) 下面我们着重理解 'is'.对于这个,我们需要知道:小整数对象池,大整数对象池,以及intern机制 小整数池:Pytho ...

  8. robot framework连接Oracle错误:ORA-12504: TNS:listener was not given the SERVICE_NAME in CONNECT_DATA

    在使用robot framework的关键字Connect to Database Using Custom params连接Oracle数据库: Connect to Database Using ...

  9. 三个月死磕Python是种什么样的体验?

    3个月的死磕Python后,参加「 楼+ Python实战 · 第4期 」的学员们感想如何?下面带来他们的真实评价. 作为实验楼的网红课程——「 楼+ Python实战 」已经走过了第四期,经过了三个 ...

  10. POJ1066:Treasure Hunt——题解

    http://poj.org/problem?id=1066 题目大意:给一个由墙围成的正方形,里面有若干墙,每次破墙只能从(当前看到的)墙的中点破,求最少破多少墙才能看到宝藏. —————————— ...