【洛谷 P7297】 【BFS】Telephone G
题目
解题思路
直接建图的话,边数太大了
考虑分层图
- 每一层之间相邻的有路,代价为1
- 第0层为输入的奶牛种类,(a[i],i)连向(0,i)
自己的颜色那一层的第i个,代价为0 - 如果两种颜色间可以互通,(0,i)连向(j,i),代价为0
然后跑一遍BFS即可
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<deque>
using namespace std;
struct lzf{
int to,z,next;
}f[9000010];
char c;
int n,m,t,d[9000010],head[9000010],a[100010],p[52][52];
inline int id(int x,int y)
{
return x*n+y;
}
inline int read()
{
int x=0;
char c=getchar();
while (c<'0'||c>'9')
c=getchar();
while (c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x;
}
inline void add(int x,int y,int z)
{
f[++t].to=y;
f[t].z=z;
f[t].next=head[x];
head[x]=t;
}
void bfs()
{
deque<int> q; //双头队列
q.push_back(1);
memset(d,0x7f,sizeof(d));
d[1]=0;
while (q.size())
{
int x=q.front();
q.pop_front();
for (int i=head[x];i;i=f[i].next)
if (d[f[i].to]==d[0])
{
d[f[i].to]=d[x]+f[i].z; //更新答案
if (f[i].z)
q.push_back(f[i].to);
else q.push_front(f[i].to); //没有代价的先跑
}
}
}
int main()
{
n=read(),m=read();
for (int i=1;i<=n;i++)
a[i]=read();
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++)
{
cin>>c;
p[i][j]=c-48;
}
for (int i=1;i<=m;i++) //每一层之间的
for (int j=1;j<n;j++)
{
add(id(i,j),id(i,j+1),1);
add(id(i,j+1),id(i,j),1);
}
for (int i=1;i<=n;i++)
{
add(id(a[i],i),i,0); //从下面往上
for (int j=1;j<=m;j++)
if (p[a[i]][j]) add(i,id(j,i),0); //从上面往下
}
bfs();
if (d[n]==d[0])
printf("-1");
else printf("%d",d[n]);
return 0;
}