版权声明:转载无所谓的。。。 https://blog.csdn.net/xuxiayang/article/details/82713834
大意
给定一些点的先决条件,问到达终点至少需要经过几个点
思路
可以把点与点之间的距离看作1,然后跑最短路
需要注意的事判断的过程中弱国一个一个去判断速度太过抵消,可以用状态压缩的方法表示一种状态,正常转移即可
代码
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;int n,m,k,l[5001],x,y,tot,key[5001],dis[5001][1025];
struct node{int next,to,need;}e[6001];
struct Node{int u,s;};
inline int read()//输入优化
{
int f=0,d=1;char c;
while(c=getchar(),c<48||c>57)if(c=='-')d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),c>47&&c<58)f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void write(register int x){if(x>9)write(x/10);putchar(x%10+48);return;}//输出优化
inline void addedge()//建边
{
int u=read(),v=read();
e[++tot].to=v;
e[tot].next=l[u];
l[u]=tot;
for(register int j=0;j<k;j++) e[tot].need|=read()<<j;//用二进制表示需要那些钥匙
return;
}
inline void special()//特判所有门都不需要钥匙的情况
{
int dis[5001];
queue<int>q;
fill(dis+1,dis+1+n,0x3f3f3f3f);
dis[1]=0;q.push(1);
while(q.size())
{
int x=q.front();q.pop();
for(register int i=l[x];i;i=e[i].next)
{
int y=e[i].to;
if(dis[y]>=0x3f3f3f3f)
{
dis[y]=dis[x]+1;
q.push(y);
}
}
}
if(dis[n]>=0x3f3f3f3f) puts("No Solution");else write(dis[n]);
}
inline void work()
{
memset(dis,0x3f,sizeof(dis));
dis[1][key[1]]=0;//初始化
queue<Node>q;
q.push((Node){1,key[1]});
while(q.size())
{
Node x=q.front();q.pop();
for(register int i=l[x.u];i;i=e[i].next)
{
if((x.s&e[i].need)!=e[i].need) continue;//如果它的钥匙对不上就跳过
int y=e[i].to,s=x.s|key[y];
if(dis[y][s]>=502345657)
{
dis[y][s]=dis[x.u][x.s]+1;
q.push((Node){y,s});
}
}
}
int ans=0x3f3f3f3f;
for(register int i=0;i<(1<<k);i++) ans=min(ans,dis[n][i]);//计算最终状态
if(ans>=0x3f3f3f3f) puts("No Solution");
else write(ans);//输出
return;
}
inline void readit()//输入
{
n=read();m=read();k=read();
for(register int i=1;i<=n;i++)
for(register int j=0;j<k;j++)
key[i]|=read()<<j;
for(register int i=1;i<=m;i++) addedge();
if(!k) special();else work();
}
signed main(){readit();}//主程序