bzoj1138 [POI2009]Baj 最短回文路 DP+宽搜
来源:互联网 发布:windows日志查询 编辑:程序博客网 时间:2024/06/06 10:04
POI就算是很老的题目也很锻炼思维啊。。。
Description
N个点用M条有向边连接,每条边标有一个小写字母。 对于一个长度为D的顶点序列,回答每对相邻顶点Si到Si+1的最短回文路径。 如果没有,输出-1。 如果有,输出最短长度以及这个字符串。
Input
第一行正整数N和M ( 2 ≤ N ≤ 400 , 1 ≤ M ≤ 60,000 ) 接下来M行描述边的起点,终点,字母。接下来D表示询问序列长度 ( 2 ≤ D ≤ 100 ) 再接下来D个1到N的整数
Output
对于D-1对相邻点,按要求输出一行。如果没合法方案,输出-1。 如果有合法,输出最短长度
Sample Input
6 7
1 2 a
1 3 x
1 4 b
2 6 l
3 5 y
4 5 z
6 5 a
3
1 5 3
Sample Output
3
-1
题意很好理解就不说了
比较容易想到枚举中间点向两边扩展,或者对于询问序列,枚举中间点,思想差不多,反正都会T。
设f[i][j]表示从i到j的最短回文路,g[i][j][k]表示从i到j的最短回文路再加上一个字符k(最后一条边不回文)。
那么我们可以用g[i][j][k]更新f[i][j],也可以反过来更新。具体来说:
然后反过来更新。
具体实现的话可能硬来不是很好,注意一下模拟链表的实现,这种trick能在关键时候给予帮助,不能小觑。
#include<cstdio>#include<algorithm>#include<cstring>#include<queue>#define mp make_pair#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=2e5+5;const int inf=0x3f3f3f3f;int n,m,tot;int head[N][27],next[N],go[N],a[N],head1[N][27];int f[405][405];int g[405][405][27];char c[N];queue<pair<int,pair<int,int> > > q;inline void add(int x,int y,int z){ go[++tot]=y;next[tot]=head[x][z];head[x][z]=tot; go[++tot]=x;next[tot]=head1[y][z];head1[y][z]=tot;}inline void bfs(){ memset(f,inf,sizeof(f)); memset(g,inf,sizeof(g)); fo(i,1,n) f[i][i]=0,q.push(mp(i,mp(i,26))); fo(i,1,n) fo(j,0,25) g[i][i][j]=0,q.push(mp(i,mp(i,j))); while (!q.empty()) { pair<int,pair<int,int> >u=q.front(); q.pop(); int x=u.first,y=u.second.first,z=u.second.second; if (z==26) { fo(i,0,25) for(int j=head[y][i];j;j=next[j]) { int v=go[j]; if (f[x][y]+1<g[x][v][i]) { g[x][v][i]=f[x][y]+1; q.push(mp(x,mp(v,i))); } } } else { for(int i=head1[x][z];i;i=next[i]) { int v=go[i]; if (g[x][y][z]+1<f[v][y]) { f[v][y]=g[x][y][z]+1; q.push(mp(v,mp(y,26))); } } } }}int main(){ scanf("%d%d",&n,&m); fo(i,1,m) { int x,y; char s[2]; scanf("%d%d%s",&x,&y,&s); f[x][y]=1; add(x,y,s[0]-'a'); } bfs(); int q,last; scanf("%d%d",&q,&last); q--; while (q--) { int x; scanf("%d",&x); printf("%d\n",f[last][x]==inf?-1:f[last][x]); last=x; } return 0;}
阅读全文
0 0
- bzoj1138 [POI2009]Baj 最短回文路 DP+宽搜
- BZOJ1138: [POI2009]Baj 最短回文路
- BZOJ1138: [POI2009]Baj 最短回文路
- BZOJ1138: [POI2009]Baj 最短回文路
- BZOJ 1138 [POI2009]Baj 最短回文路 DP
- [BZOJ 1138] POI2009 Baj 最短回文路
- BZOJ 1138 POI2009 Baj 最短回文路 BFS
- bzoj 1138: [POI2009]Baj 最短回文路 bfs
- bzoj-1138 Baj 最短回文路
- 最短回文串
- 【DP】BAJ-Bytecomputer
- 最短回文串 题解
- [作业]最短回文串
- 最短回文测试结果
- 【DP,lcs问题】最短回文串(palindrome.pas/c/cpp)
- 关于最短分割回文的实现
- Leetcode Shortest Palindrome (最短回文串)
- [LeetCode] Shortest Palindrome 最短回文串
- Spring学习笔记(一)IOC
- LintCode:H-Sliding Window Median
- C#基础-006(3) 判断一个年份是否为闰年
- python实现-明明的随机数
- DOS XML
- bzoj1138 [POI2009]Baj 最短回文路 DP+宽搜
- 实用对拍
- poj2341 Expedition
- 动态注册广播判断网络,跳转到设置页面
- UVA
- 子雨大数据之Spark入门教程---Spark简介1.1
- 常用浏览器内核驱动下载地址
- 数据库索引及分类
- python学习day01