[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. ...
随机推荐
- MyEclipse去除不必要的validation
MyEclipse在构建项目时去除不必要的Valication可以加快构建速度. 操作: Window->Perferences->MyEclipse->Validation 在Va ...
- Plugging an Unplugged Pluggable Database issue 3
Multitenant Unplug/Plug Best Practices (文档 ID 1935365.1) 1.source 从0419 升级到1019 ,但是datapatch 没有回退041 ...
- 473 Matchsticks to Square 火柴拼正方形
还记得童话<卖火柴的小女孩>吗?现在,你知道小女孩有多少根火柴,请找出一种能使用所有火柴拼成一个正方形的方法.不能折断火柴,可以把火柴连接起来,并且每根火柴都要用到.输入为小女孩拥有火柴的 ...
- ABP教程(二)- 将ABP在本地运行起来
上一篇 我们介绍了什么是ABP,这一篇我们通过原作者的”简单任务系统”例子,演示如何运用ABP开发项目 从模板创建空的web应用程序 ABP提供了一个启动模板用于新建的项目(尽管你能手动地创建项目并且 ...
- mvc的生命周期
尽管每次都是从msdn里复制粘贴,但是还是有必要的,加深对mvc的理解和官方的表述. 了解 MVC 应用程序执行过程 发送给基于 ASP.NET MVC 的 Web 应用程序的请求首先通过 UrlRo ...
- 支付宝SDK
由于支付宝SDK对于整个支付流程已经介绍的十分详细了,在这里我就简单说一些注意点. 由于存在支付宝可能没有安装的情况,所以我们在调用支付宝支付时,需要对其进行判断,做出不同的处理方式,即是使用客户端支 ...
- iOS Programming Camera 2
iOS Programming Camera 2 1.1 Creating BNRImageStore The image store will fetch and cache the image ...
- System.Lazy<T>延迟加载
在很多情况下,有些对象需要在使用时加载或根据逻辑动态加载.有些情况如果不延迟加载,可能会影响效率甚至抛出Timeout Exception.如网络操作.数据库操作.文件IO操作 直接上代码,方便我们理 ...
- 【C++】模板简述(二):函数模板
我们上文讲了,模板的引入,我们发现在某种特殊的情况下,必须得通过模板才能完美的解决问题. 本文就来简述一下函数模板的基本使用. 一.函数模板格式 template<typename Param1 ...
- rem手机端页面自适应完美解决方案(最新)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...