dp+spfa优化

最朴素的dp是dp[i][j]表示i->j的最短路,然后把所有pair(i,i)放到队列里跑spfa,但是这样被卡掉了,那么我们要优化一下

问题在于每次我们转移的时候要枚举i和j的邻居,这样会被两个连起来的菊花卡掉,那么我们希望一次只走一步,那么复杂度会大大降低,于是我们设一个状态g[i][j][k],表示当前在i,j,上一条出边的字符为k,这样我们让f和g交替转移,达到了每次只走一步的目标,然后就能过了,原先每次转移最坏O(m*m)?现在大概是O(n*m)的转移,状态数O(n*n*26)

#include<bits/stdc++.h>
using namespace std;
const int N = , inf = 0x3f3f3f3f;
struct edge {
int nxt, to, c;
} e[N * N << ];
struct node {
int u, v, c;
node(int u, int v, int c) : u(u), v(v), c(c) {}
};
int n, m, cnt = , q, last;
int head1[N], head2[N], f[N][N], g[N][N][], vis[N][N][];
void link1(int u, int v, int c)
{
e[++cnt].nxt = head1[u];
head1[u] = cnt;
e[cnt].to = v;
e[cnt].c = c;
}
void link2(int u, int v, int c)
{
e[++cnt].nxt = head2[u];
head2[u] = cnt;
e[cnt].to = v;
e[cnt].c = c;
}
void bfs()
{
queue<node> q;
memset(f, inf, sizeof(f));
memset(g, inf, sizeof(g));
for(int i = ; i <= n; ++i) vis[i][i][] = , f[i][i] = , q.push(node(i, i, ));
for(int i = ; i <= n; ++i)
for(int j = ; j < ; ++j) vis[i][i][j] = , g[i][i][j] = , q.push(node(i, i, j));
while(!q.empty())
{
node o = q.front();
q.pop();
int u = o.u, v = o.v;
vis[u][v][o.c] = ;
if(o.c == )
{
for(int i = head1[v]; i; i = e[i].nxt) if(g[u][e[i].to][e[i].c] > f[u][v] + )
{
g[u][e[i].to][e[i].c] = f[u][v] + ;
if(!vis[u][e[i].to][e[i].c])
{
vis[u][e[i].to][e[i].c] = ;
q.push(node(u, e[i].to, e[i].c));
}
}
}
else
{
for(int i = head2[u]; i; i = e[i].nxt) if(e[i].c == o.c && f[e[i].to][v] > g[u][v][o.c])
{
f[e[i].to][v] = g[u][v][o.c] + ;
if(!vis[e[i].to][v][])
{
vis[e[i].to][v][] = ;
q.push(node(e[i].to, v, ));
}
}
}
}
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = ; i <= m; ++i)
{
int u, v;
char c[];
scanf("%d%d%s", &u, &v, c);
link1(u, v, c[] - 'a');
link2(v, u, c[] - 'a');
}
bfs();
scanf("%d%d", &q, &last);
q--;
while(q--)
{
int x;
scanf("%d", &x);
printf("%d\n", f[last][x] == inf ? - : f[last][x]);
last = x;
}
return ;
}

bzoj1138的更多相关文章

  1. [BZOJ1138][POI2009]Baj 最短回文路

    [BZOJ1138][POI2009]Baj 最短回文路 试题描述 N个点用M条有向边连接,每条边标有一个小写字母. 对于一个长度为D的顶点序列,回答每对相邻顶点Si到Si+1的最短回文路径. 如果没 ...

随机推荐

  1. BZOJ2662[BeiJing wc2012]冻结【SPFA】

    “我要成为魔法少女!” “那么,以灵魂为代价,你希望得到什么?” “我要将有关魔法和奇迹的一切,封印于卡片之中„„”        在这个愿望被实现以后的世界里,人们享受着魔法卡片(SpellCard ...

  2. [codevs] 1699 开关灯

    题目描述 Description YYX家门前的街上有N(2<=N<=100000)盏路灯,在晚上六点之前,这些路灯全是关着的,六点之后,会有M(2<=m<=100000)个人 ...

  3. 1716: [Usaco2006 Dec]The Fewest Coins 找零钱

    n<=100种硬币,给每种的硬币的面额<=120和我每种有多少个<=10000,店主的硬币跟我一样但有无限个,求买t<=10000块钱的东西钱最少转手几次. 我拿的硬币最少几次 ...

  4. Python基础教程笔记——第6章:抽象(函数)

    (1)计算裴波那契数列: fbis=[0,1] num=int(input("please input the number")) for i in range(num-2): f ...

  5. 快速让你明白Objective-C的语法(和Java、C++对比)

    很多想开发iOS,或者正在开发iOS的程序员以前都做过Java或者C++,当第一次看到Objective-C的代码时都会头疼,Objective-C的代码在语法上和Java, C++有着很大的区别,有 ...

  6. HDU 1028 整数拆分 HDU 2082 找单词 母函数

    生成函数(母函数) 母函数又称生成函数.定义是给出序列:a0,a1,a2,...ak,...an, 那么函数G(x)=a0+a1*x+a2*x2+....+ak*xk +...+an* xn  称为序 ...

  7. HDU1533 最小费用最大流

    Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  8. 问题解决:FFmpeg视频编解码库,无法解析的外部信号

    在编译FFmpeg相关项目时.可能会出现: error LNK2019: 无法解析的外部符号 "int __cdecl avpicture_fill(struct AVPicture *,u ...

  9. [正在学习开发板]分享--- iTOP-4412移植CAN

    首先拷贝迅为提供的 libcanjni.tar.gz 压缩包到 android 源代码的"iTop4412_ICS/device/samsung/common"文件夹以下,然后使用 ...

  10. JAVA学习(一):Java介绍及其平台、开发环境的配置与搭建

    Java介绍及其平台.开发环境的配置与搭建 1.Java的介绍 Java是一种面向对象的编程语言,具有跨平台.可移植.分布式.简单.可扩展等诸多特性.Java能够进行桌面应用.Web应用.分布式系统及 ...