[BZOJ1138][POI2009]Baj 最短回文路
[BZOJ1138][POI2009]Baj 最短回文路
试题描述
输入
输出
对于D-1对相邻点,按要求输出一行。如果没合法方案,输出-1。 如果有合法,输出最短长度
输入示例
a
x
b
l
y
z
a
输出示例
-
数据规模及约定
见“输入”
题解
朴素的 dp 是这样的:设 f[i][j] 表示节点 i 到节点 j 的最短回文长度,转移的时候枚举字母 x,设节点 j 沿着带有字母 x 的边走一格所能到达的点集为集合 A,设 i 逆着带有字母 x 的边走一格所能达到的点集为集合 B。那么对于 ∀a ∈ A, ∀b ∈ B,就可以更新 f[a][b] 了,即 f[a][b] = min{ f[a][b], f[i][j] + 2 }。
但是我们发现这个算法被爆菊了。。。就是如果有很多条相同字母的边指向 i,相同字母的边从 j 出发,转移就会被卡成 O(n2) 的了。。。
解决方式就是添加一个中间状态 g[i][j][c],表示节点 i 到节点 j 的路径最后一个字母是 c,并且除掉最后一个字母后它就是一个回文路径,在这样的情况下的最短长度。那么对于状态 f[i][j],可以用节点 j 沿着字母 c(枚举)走一格到达的所有节点 b 来更新 g[i][b][c];对于状态 g[i][b][c],可以用节点 i 逆着字母 c(这个字母是固定的,即状态中的字母)走一格到达的所有节点 a 来更新 f[a][b],这样状态数变成了原来的 27 倍,转移复杂度变成了 O(n)。
转移顺序比较乱,可以用 BFS 帮助转移。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <queue>
using namespace std; int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 410
#define maxa 26
#define maxm 10660 bool G[maxn][maxn][maxa];
int f[maxn][maxn], g[maxn][maxn][maxa];
vector <int> from[maxn][maxa], to[maxn][maxa];
void AddEdge(int a, int b, int c) {
to[a][c].push_back(b);
from[b][c].push_back(a);
return ;
} struct Pair {
int a, b, c;
Pair() {}
Pair(int _1, int _2, int _3): a(_1), b(_2), c(_3) {}
};
queue <Pair> Q; int main() {
int n = read(), m = read();
for(int i = 1; i <= m; i++) {
int a = read(), b = read(); char ch[2]; scanf("%s", ch);
G[a][b][ch[0]-'a'] = 1;
} memset(f, -1, sizeof(f)); memset(g, -1, sizeof(g));
for(int i = 1; i <= n; i++) Q.push(Pair(i, i, -1)), f[i][i] = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++) if(i != j) {
bool fl = 0;
for(int c = 0; c < maxa; c++) if(G[i][j][c]) {
AddEdge(i, j, c);
fl = 1; break;
}
if(fl) f[i][j] = 1, Q.push(Pair(i, j, -1));
}
while(!Q.empty()) {
Pair u = Q.front(); Q.pop();
int a = u.a, b = u.b, c = u.c, tmp = c < 0 ? f[a][b] : g[a][b][c];
// printf("(%d, %d, %d)\n", a, b, c);
if(c < 0)
for(c = 0; c < maxa; c++)
for(int i = 0; i < to[b][c].size(); i++) {
int B = to[b][c][i];
if(g[a][B][c] < 0) g[a][B][c] = tmp + 1, Q.push(Pair(a, B, c));
}
else
for(int i = 0; i < from[a][c].size(); i++) {
int A = from[a][c][i];
if(f[A][b] < 0) f[A][b] = tmp + 1, Q.push(Pair(A, b, -1));
}
} int q = read(), st = read();
for(int i = 2; i <= q; i++) {
int u = read();
printf("%d\n", f[st][u]);
st = u;
} return 0;
}
[BZOJ1138][POI2009]Baj 最短回文路的更多相关文章
- bzoj 1138: [POI2009]Baj 最短回文路 dp优化
1138: [POI2009]Baj 最短回文路 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 161 Solved: 48[Submit][Sta ...
- bzoj 1138: [POI2009]Baj 最短回文路
额,,貌似网上的题解都说超时之类的. 然而我这个辣鸡在做的时候不知道在想什么,连超时的都不会. 超时的大概是这样的,f[x][y]表示x到y的最短回文路,然后更新的话就是 f[x][y]更新到 f[a ...
- [Swift]LeetCode214. 最短回文串 | Shortest Palindrome
Given a string s, you are allowed to convert it to a palindrome by adding characters in front of it. ...
- [python,2019-02-15] 最短回文串
给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串.找到并返回可以用这种方式转换的最短回文串. 示例 1: 输入: "aacecaaa" 输出: "aaa ...
- leetcode 214. 最短回文串 解题报告
给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串.找到并返回可以用这种方式转换的最短回文串. 示例 1: 输入: "aacecaaa" 输出: "aaa ...
- 214 Shortest Palindrome 最短回文串
给一个字符串 S, 你可以通过在字符串前面添加字符将其转换为回文串.找到并返回可以用这种方式转换的最短回文串.例如:给出 "aacecaaa",返回 "aaacecaaa ...
- Leetcode 214.最短回文串
最短回文串 给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串.找到并返回可以用这种方式转换的最短回文串. 示例 1: 输入: "aacecaaa" 输出: &qu ...
- Java实现 LeetCode 214 最短回文串
214. 最短回文串 给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串.找到并返回可以用这种方式转换的最短回文串. 示例 1: 输入: "aacecaaa" 输出 ...
- [LeetCode] Shortest Palindrome 最短回文串
Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. ...
随机推荐
- 题解报告:poj 3320 Jessica's Reading Problem(尺取法)
Description Jessica's a very lovely girl wooed by lots of boys. Recently she has a problem. The fina ...
- Matlab实现Hough变换检测图像中的直线 分类: 图像处理 2014-06-14 22:07 641人阅读 评论(0) 收藏
Hough变换的原理: 将图像从图像空间变换至参数空间,变换公式如下: 变换以后,图像空间与参数空间存在以下关系: 图像空间中的一点在参数空间是一条曲线,而图像空间共线的各点对应于参数空间交于一点的各 ...
- linux下的c程序排版工具:indent 分类: linux 2014-06-14 20:05 720人阅读 评论(0) 收藏
Linux下有一个方便的c语言程序排版工具,只要选择恰当的参数,可以轻易地使自己的程序具有统一的风格. 当然首先要安装indent,执行命令:apt-get install indent indent ...
- .vimrc文件配置及含意
1. vimrc文件常见语句释义 设定 tab 的位置 :set tabstop=4 输入 tab 时自动将其转化为空格 :set expandtab ...
- poj3735Training little cats
链接 构造矩阵 快速幂求解 构造矩阵a[i]为每个cati所拥有的花生总数 这里多加一维用来求和,具体是怎么求得可以看下面的一组例子 假设有3个cat a[] = {1,0,0,0} 构造单位矩阵来保 ...
- mybatis的mapper.xml文件细节
- ScrollView嵌套GridView,GridView显示不全
最近开发有个需求是以A-Z的方式区分全国城市(搜索功能),并实现字母索引的功能(有点类似微信,不过比较坑的是用的是GridView, 并且GridView上面还有几个LinearLayout). 详细 ...
- R in action读书笔记(19)第十四章 主成分和因子分析
第十四章:主成分和因子分析 本章内容 主成分分析 探索性因子分析 其他潜变量模型 主成分分析(PCA)是一种数据降维技巧,它能将大量相关变量转化为一组很少的不相关变量,这些无关变量称为主成分.探索性因 ...
- Farseer.net轻量级开源框架 中级篇:UrlRewriter 地址重写
导航 目 录:Farseer.net轻量级开源框架 目录 上一篇:Farseer.net轻量级开源框架 中级篇: Cookies.Session.Request 下一篇:Farseer.net轻量 ...
- sql中的日期时间处理
每个数据库,不同的日期格式化: 1.mysql 2.sqlserver 使用Convert()函数: select convert(char(10),GetDate(),120) as Date 第3 ...