2018年9月15日提高组模拟赛 T3 密室

版权声明:转载无所谓的。。。 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();}//主程序

猜你喜欢

转载自blog.csdn.net/xuxiayang/article/details/82713834