题意:给定N点M边的有向图,每条边有距离和颜色,一条有效路径上不能有相邻的边颜色相同。现在给定起点S,多次讯问S到点X的最短有效距离。

TLE思路:用二维状态dis(u,c)表示起点到u,最后一条边的颜色是c的最短距离,用map解决了二维空间不足的问题。但是T第151个点。所以需要优化,标解的优化是把dis(u,c)改为dis(u,0)或者dis(u,1)分别表示颜色同和不同的最短距离。

其他思路:用边表示通过那条边到点的最短距离。由于边自带颜色属性,所以就不需要其他状态了。这个方法比较直观,可以直接看代码。

TLE代码:(加了优化也不行。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
#define pii pair<int,int>
#define mp make_pair
#define Fi first
#define Se second
using namespace std;
const int maxn=;
const ll inf=1LL<<;
int Laxt[maxn],Next[maxn],To[maxn],W[maxn],C[maxn];
int S,N,cnt; ll ans[maxn];
deque<pii>q;
map<int,ll>dis[maxn];
map<int,int>vis[maxn];
void add(int u,int v,int w,int c){
Next[++cnt]=Laxt[u];Laxt[u]=cnt;To[cnt]=v; W[cnt]=w; C[cnt]=c;
}
void spfa()
{
rep(i,,N) ans[i]=inf; ans[S]=;
for(int i=Laxt[S];i;i=Next[i]){
dis[To[i]][C[i]]=W[i]; ans[To[i]]=W[i];
vis[To[i]][C[i]]=;
if(!q.empty()&&dis[To[i]][C[i]]<dis[q.front().Fi][q.front().Se])
q.push_front(mp(To[i],C[i]));
else q.push_back(mp(To[i],C[i]));
}
while(!q.empty()){
pii H=q.front(); q.pop_front();
int u=H.Fi,c=H.Se; ll tdis=dis[u][c]; vis[u][c]=;
for(int i=Laxt[u];i;i=Next[i]){
int v=To[i];
if(c==C[i]) continue;
if(dis[v].find(C[i])==dis[v].end()){
dis[v][C[i]]=tdis+W[i];
ans[v]=min(ans[v],dis[v][C[i]]);
if(!vis[v][C[i]]){
vis[v][C[i]]=;
if(!q.empty()&&dis[v][C[i]]<dis[q.front().Fi][q.front().Se]) q.push_front(mp(v,C[i]));
else q.push_back(mp(v,C[i]));
}
}
else if(tdis+W[i]<dis[v][C[i]]){
dis[v][C[i]]=tdis+W[i];
ans[v]=min(ans[v],dis[v][C[i]]);
if(!vis[v][C[i]]){
vis[v][C[i]]=;
if(!q.empty()&&dis[v][C[i]]<dis[q.front().Fi][q.front().Se]) q.push_front(mp(v,C[i]));
else q.push_back(mp(v,C[i]));
}
}
}
}
rep(i,,N) if(ans[i]==inf) ans[i]=-;
}
int main()
{
int M,CC,Q,u,v,w,c;
scanf("%d%d%d",&N,&M,&CC);
rep(i,,M){
scanf("%d%d%d%d",&u,&v,&w,&c);
add(u,v,w,c);
}
scanf("%d%d",&S,&Q);
spfa();
while(Q--){
scanf("%d",&u);
printf("%I64d\n",ans[u]);
}
return ;
}

AC代码:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
const int maxn=;
const ll inf=1LL<<;
int Laxt[maxn],Next[maxn],To[maxn],W[maxn],C[maxn];
int S,N,cnt,vis[maxn]; ll ans[maxn],dis[maxn];
void add(int u,int v,int w,int c){
Next[++cnt]=Laxt[u];Laxt[u]=cnt;To[cnt]=v; W[cnt]=w; C[cnt]=c;
}
void spfa()
{
deque<int>q;
rep(i,,N) ans[i]=inf; ans[S]=;
rep(i,,cnt) dis[i]=inf;
for(int i=Laxt[S];i;i=Next[i]){
dis[i]=W[i]; q.push_back(i); vis[i]=;
}
while(!q.empty()){
int u=q.front(); q.pop_front(); vis[u]=;
for(int i=Laxt[To[u]];i;i=Next[i]){
if(C[u]!=C[i]){
if(dis[i]>dis[u]+W[i]){
dis[i]=dis[u]+W[i];
if(!vis[i]) {
vis[i]=;
if(!q.empty()&&dis[i]<dis[q.front()]) q.push_front(i); //注意不要为空
else q.push_back(i);
}
}
}
}
}
rep(i,,cnt) ans[To[i]]=min(ans[To[i]],dis[i]);
rep(i,,N) if(ans[i]==inf) ans[i]=-;
}
int main()
{
int M,CC,Q,u,v,w,c;
scanf("%d%d%d",&N,&M,&CC);
rep(i,,M){
scanf("%d%d%d%d",&u,&v,&w,&c);
add(u,v,w,c);
}
scanf("%d%d",&S,&Q);
spfa();
while(Q--){
scanf("%d",&u);
printf("%I64d\n",ans[u]);
}
return ;
}

Gym - 100570B :ShortestPath Query(SPFA及其优化)的更多相关文章

  1. codeforce Gym 100570B ShortestPath Query (最短路SPFA)

    题意:询问单源最短路径,每条边有一个颜色,要求路径上相邻边的颜色不能相同,无重边且边权为正. 题解:因为路径的合法性和边的颜色有关, 所以在做spfa的时候,把边丢到队列中去,松弛的时候注意判断一下颜 ...

  2. SPFA 小优化*2

    /* bzoj 2763 SPFA小优化 循环队列+SLF 顺面改掉自己之前手打qeueu的坏毛病*/ #include<iostream> #include<cstring> ...

  3. HDU 1535 Invitation Cards(SPFA,及其优化)

    题意: 有编号1-P的站点, 有Q条公交车路线,公交车路线只从一个起点站直接到达终点站,是单向的,每条路线有它自己的车费. 有P个人早上从1出发,他们要到达每一个公交站点, 然后到了晚上再返回点1. ...

  4. [BZOJ 2200][Usaco2011 Jan]道路和航线 spfa+SLF优化

    Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...

  5. 【最短路径】 SPFA算法优化

    首先先明确一个问题,SPFA是什么?(不会看什么看,一边学去,传送门),SPFA是bellman-ford的队列优化版本,只有在国内才流行SPFA这个名字,大多数人就只知道SPFA就是一个顶尖的高效算 ...

  6. SPFA队列优化

    spfa队列优化(用来求最短路) 实现方法: 1.存入图.可以使用链式前向星或者vocter. 2.开一个队列,先将开始的节点放入. 3.每次从队列中取出一个节点X,遍历与X相通的Y节点,查询比对   ...

  7. spfa + slf优化

    最近在练习费用流 , 不是要用spfa吗 ,我们教练说:ns学生写朴素的spfa说出去都让人笑 . QwQ,所以就去学了一下优化 . slf优化就是双向队列优化一下,本来想用lll优化,可是优化后我t ...

  8. 最短路--spfa+队列优化模板

    spfa普通版就不写了,优化还是要的昂,spfa是可以判负环,接受负权边和重边的,判断负环只需要另开一个数组记录每个结点的入队次数,当有任意一个结点入队大于点数就表明有负环存在 #include< ...

  9. CDOJ 1287 MC挖矿世界(Spfa+set优化)

    题目大意:原题链接 解题思路:此题要求多点最短距离,但是直接套用floyd会超时. 然后我们想直接从每一个点开始bfs就好了,但是还是会TLE,为什么呢? 因为你访问了很多次没有意义的地方,因为有些点 ...

随机推荐

  1. Android源码及repo下载——亲自测试下载源码成功!

    经过一段时间煞费苦心的下载都未能成功后,如今终于把android源代码下载成功,很是兴奋! 废话不多说,直接说下步骤: 1.安装git和curl:sudo apt-get install git-co ...

  2. 【CodeM初赛B轮】A 贪心

    [CodeM初赛B轮]A 题目大意:给你一棵树,起初所有点都是白色的,你每次都能选择一个白点i,将这个点i到根路径上的所有到i的距离<k[i]的点都染成黑色(根和i也算,已经被染成黑色的点还是黑 ...

  3. ResfulApi规范

    序号 方法 描述 1 GET 请求指定的页面信息,并返回实体主体. 2 HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头 3 POST 向指定资源提交数据进行处理请求(例如提 ...

  4. 基于镜像安装mysql

    准备目录 cd /opt mkdir -p mysql/data mysql/logs mysql/conf 查找MySql镜像版本 docker search mysql 安装指定版本的mysql镜 ...

  5. 九度OJ 1180:对称矩阵 (矩阵计算)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2637 解决:1354 题目描述: 输入一个N维矩阵,判断是否对称. 输入: 输入第一行包括一个数:N(1<=N<=100),表 ...

  6. 反应器模式 vs 生产者消费者模式

    相似点: 从结构上,反应器模式有点类似生产者消费者模式,即有一个或多个生产者将事件放入一个Queue中,而一个或多个消费者主动的从这个Queue中Poll事件来处理: 不同点: Reactor模式则并 ...

  7. 原来还有cookie-free domain这么回事

    cookie-free domain的解释:在请求下载静态小图片.静态小文件的时候,浏览器会把它当成普通请求一样,在request的header信息里附加cookie信息. 但实际上,99.99%的静 ...

  8. KVM虚拟化技术实战全过程

    今天准备开始.................... centos安装-kvm 教程: http://www.linuxidc.com/Linux/2017-01/140007.htm http:// ...

  9. memcached 不同客户端的问题

    摘要: memcached-java客户端调用get方法获取数据失败 主要演示一下在memcached服务器端set数据之后,在客户端调用java api获取数据.不过此过程如果不慎会读取数据失败. ...

  10. 读paper:image caption with global-local attention…

    最近的图片caption真的越来越火了,CVPR ICCV ECCV AAAI很多顶级会议都有此类的文章,今天我来讲一篇发表在AAAI的文章,因为我看了大量的论文,最近感觉AAAI越来越水了.所以这篇 ...