本人将自己的 AC 代码(如下):
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,k,s,t,u,v,w,wh[101],dist[101],ans=0x3f3f3f3f;
bool vis[101],lp=false;
bool tcp[101][101];
struct edge{
int ed,len;
};
bool operator<(edge mk,edge k){
return mk.len>k.len;
}
vector<edge>e[101],el[101];
priority_queue<edge>q;
void Dijkstra(int begin){
memset(dist,0x3f3f3f3f,sizeof(dist));
memset(vis,false,sizeof(vis));
q.push(edge{begin,0});
dist[begin]=0;
while(!q.empty()){
edge d=q.top();
q.pop();
if(vis[d.ed])continue;
vis[d.ed]=true;
for(int i=0;e[d.ed].size()>i;i++){
if(dist[e[d.ed][i].ed]>dist[d.ed]+e[d.ed][i].len){
dist[e[d.ed][i].ed]=dist[d.ed]+e[d.ed][i].len;
q.push(edge{e[d.ed][i].ed,dist[e[d.ed][i].ed]});
}
}
}
}
inline void srh(int p,int d,int dt[]){
if(!vis[p]||(lp&&dist[p]+d>=ans))return;
if(p==t){
ans=d;
lp=true;
return;
}
dt[wh[p]]++;
for(int i=0;el[p].size()>i;i++){
for(int j=1;j<=k;j++){
if(tcp[wh[el[p][i].ed]][j]&&dt[j]!=0)goto end;
}
if(!(!vis[el[p][i].ed]||(lp&&dist[el[p][i].ed]+d+el[p][i].len>=ans))){
srh(el[p][i].ed,d+el[p][i].len,dt);
}
end:continue;
}
dt[wh[p]]--;
}
int r[101];
int main(){
scanf("%d%d%d%d%d",&n,&k,&m,&s,&t);
for(int i=1;i<=n;i++){
scanf("%d",&wh[i]);
}
for(int i=1;i<=k;i++){
for(int j=1;j<=k;j++){
scanf("%d",&u);
if(j==i)u=1;
tcp[i][j]=u;
}
}
if(tcp[wh[t]][wh[s]]){
printf("-1");
return 0;
}
for(int i=1;m>=i;i++){
scanf("%d%d%d",&u,&v,&w);
if(tcp[wh[v]][wh[u]])continue;
e[v].push_back(edge{u,w});
el[u].push_back(edge{v,w});
}
Dijkstra(t);
srh(s,0,r);
if(lp)printf("%d",ans);
else printf("-1");
return 0;
}
改为如下:
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,k,s,t,u,v,w,wh[101],dist[101],ans=0x3f3f3f3f;
__int128 tcp[101];
bool vis[101],lp=false;
struct edge{
int ed,len;
};
bool operator<(edge mk,edge k){
return mk.len>k.len;
}
vector<edge>e[101],el[101];
priority_queue<edge>q;
void Dijkstra(int begin){
memset(dist,0x3f3f3f3f,sizeof(dist));
memset(vis,false,sizeof(vis));
q.push(edge{begin,0});
dist[begin]=0;
while(!q.empty()){
edge d=q.top();
q.pop();
if(vis[d.ed])continue;
vis[d.ed]=true;
for(unsigned i=0;i<e[d.ed].size();i++){
if(dist[e[d.ed][i].ed]>dist[d.ed]+e[d.ed][i].len){
dist[e[d.ed][i].ed]=dist[d.ed]+e[d.ed][i].len;
q.push(edge{e[d.ed][i].ed,dist[e[d.ed][i].ed]});
}
}
}
}
inline void srh(register int p,register int d,register __int128 sl){
if(!vis[p]||(lp&&dist[p]+d>=ans))return;
if(p==t){
ans=d;
lp=true;
return;
}
sl+=((__int128)1<<k-wh[p]);
for(register unsigned i=0;el[p].size()>i;i++){
if((tcp[wh[el[p][i].ed]]&sl)==0){
srh(el[p][i].ed,d+el[p][i].len,sl);
}
}
}
int main(){
scanf("%d%d%d%d%d",&n,&k,&m,&s,&t);
for(register int i=1;i<=n;i++){
scanf("%d",&wh[i]);
}
for(int i=1;i<=k;i++){
for(int j=1;j<=k;j++){
scanf("%d",&u);
if(j==i)u=1;
tcp[i]=tcp[i]*2+u;
}
}
for(int i=1;m>=i;i++){
scanf("%d%d%d",&u,&v,&w);
e[v].push_back(edge{u,w});
el[u].push_back(edge{v,w});
}
Dijkstra(t);
srh(s,0,(__int128)0);
if(lp)printf("%d",ans);
else printf("-1");
return 0;
}
即改为利用 __int128 进行位运算,本以为可以更快,结果反而 TLE 92pts,想知道是为什么。