1 条题解
-
0Guest LV 0
-
0
#include<bits/stdc++.h>
using namespace std;
int n,m,k,x,y;
struct Edge
{
int next;
int dis;
int to;
}edge[100000];
struct node
{
int w,key;//w表示房间号 key表示当前房间钥匙情况
};
int head[10000];
int room[5010];//room记录每个房间钥匙情况
int vis[5010][1024];//vis记录每个房间能否行走情况
int w[6010];
int cnt=0;//编号
inline void add(int from,int to,int dis)
{
edge[++cnt].next=head[from];
edge[cnt].to=to;
edge[cnt].dis=dis;
head[from]=cnt;
}
inline void add_SPFA(int from,int to,int dis)
{
edge[++cnt].next=head[from];
edge[cnt].to=to;
edge[cnt].dis=dis;
head[from]=cnt;
}
int main()
{
cin>>n>>m>>k;
if(k==0)
{//Dijkstra
bool check[10000]={0};
long long diss[10000];
for(int i=1;i<=n;i++) diss[i]=2147483647;
for(int i=1;i<=m;i++)
{
cin>>x>>y;
add(x,y,1);
}
int curr=1;
diss[1]=0;
long long minn;
while(!check[curr])
{
check[curr]=true;
for(int i=head[curr];i!=0;i=edge[i].next)
{
if(!check[edge[i].to]&&diss[edge[i].to]>diss[curr]+edge[i].dis)
diss[edge[i].to]=diss[curr]+edge[i].dis;
}
minn=2147483647;
for(int i=1;i<=n;i++)
{
if(!check[i]&&minn>diss[i])
{
minn=diss[i];
curr=i;
}
}
}
if(diss[n]==2147483647) cout<<"No Solution"<<endl;
else cout<<diss[n]<<endl;
}
if(k!=0)
{//SPFA
queue<node> q;//开q队列 //要写在主函数内
long long diss[10000];
for(int i=1;i<=n;i++)
{//记录房间钥匙
int key=0;
for(int j=0;j<k;j++)//j从0开始 因为这里用到位运算
{
int t;
cin>>t;
key|=(t<<j);//将t左移j位与key进行 或运算 并将运算结果赋值给key
} //或运算 有1 结果就为1 (两者都为0结果才为0)
room[i]=key;//记录i房间需要的钥匙情况
}
for(int i=1;i<=m;i++)
{//记录边的钥匙
int key=0;
cin>>x>>y;
for(int j=0;j<k;j++)
{
int t;
cin>>t;
key|=(t<<j);
}
add_SPFA(x,y,key);//在这里可以把每一条边上的钥匙情况当做该边的权值进行计算
}
for(int i=1;i<=n;i++) diss[i]=2147483647;//初始化每个点的距离为INF
diss[1]=0;
node temp;
temp.w=1;
temp.key=room[1];
vis[1][room[1]]=1;//第一个房间可走
q.push(temp);//将第一个房间入队
while(!q.empty())//SPFA算法中的2步骤 循环计算直到队列为空
{
node u=q.front();//返回队列第一个值
q.pop();//删除队列第一个值
int a=u.w,b=u.key;//记录队列第一个的房间号和钥匙情况 在这里实际上就是取出一个有父无子的房间
vis[a][b]=0;
for(int i=head[a];i;i=edge[i].next)
{
if((edge[i].dis&b)==edge[i].dis)//如果这个有父无子的房间有下一条路要求的钥匙
{
int v=edge[i].to;//v 下一个将连的房间
if(diss[v]>diss[a]+1)
{
diss[v]=diss[a]+1;
int near_key=(b|room[v]);//记录下一个将连的房间目前钥匙情况
if(!vis[v][near_key])// 如果下一个将连接的房间还未走过
{
vis[v][near_key]=1;
node t;
t.w=v;
t.key=near_key;
q.push(t);//将已确立的下一个房间入队
}
}
}
}
}
if(diss[n]==2147483647) cout<<"No Solution"<<endl;
else cout<<diss[n]<<endl;
}
return 0;
}
//来自某届石光中学信竞苟蒻学长 愿看到此文的你 努力码题 为校争光
- 1
信息
- 难度
- 9
- 分类
- (无)
- 标签
- 递交数
- 11
- 已通过
- 2
- 通过率
- 18%
- 上传者