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. bzoj1086 [SCOI2005]王室联邦 树分块

    [bzoj1086][SCOI2005]王室联邦 2014年11月14日2,6590 Description “余”人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的 ...

  2. 没有上司的舞会(hdu 1520)

    题目描述 Description Ural大学有N个职员,编号为1~N.他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.每个职员有一个快乐指数.现在有个周年庆宴会 ...

  3. [NOIP2003] 提高组 洛谷P1039 侦探推理

    题目描述 明明同学最近迷上了侦探漫画<柯南>并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏.游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯(在明明不知情的情况下),明 ...

  4. Linux下出现launch failed.Binary not found的解决方案

    Linux下出现launch failed.Binary not found的解决方案: Project->Properties->C/C++Build->Settings-> ...

  5. POJ 2109 Power of Cryptography【高精度+二分 Or double水过~~】

    题目链接: http://poj.org/problem?id=2109 参考: http://blog.csdn.net/code_pang/article/details/8263971 题意: ...

  6. POJ 1094 Sorting It All Out【拓扑排序】

    题目链接: http://poj.org/problem?id=1094 题意: 给定前n个字母的大小关系,问你是否 根据前xxx个关系得到上升序列 所有关系都无法确定唯一的一个序列 第xxx个关系导 ...

  7. Codeforces 938G(cdq分治+可撤销并查集+线性基)

    题意: 有一个无向连通图,支持三个操作: 1 x y d : 新建一条x和y的无向边,长度为d 2 x y    :删除x和y之间的无向边 3 x y    :询问x到y的所有路径中(可以绕环)最短的 ...

  8. 105. Construct Binary Tree from Inorder and preorder Traversal

    /* * 105. Construct Binary Tree from Inorder and preorder Traversal * 11.20 By Mingyang * 千万不要以为root ...

  9. Java后端技术书单

    写博客记录技术上使用的各种问题,这个只能算是一个打游击. 如果要把一个知识学透,最有效的方式就是系统学习,而系统学习就是看书,书本上有清晰的学习路线以及相应的技术栈. 下面是我收集的Java后端的技术 ...

  10. java集合框架 hashMap 简单使用

    参考文章:http://blog.csdn.net/itm_hadf/article/details/7497462 通常,默认加载因子 (.75) 在时间和空间成本上寻求一种折衷.      加载因 ...