NCST--HBCPC2021选拔赛C

Chase

来源:http://acm.ncst.edu.cn/problem.php?cid=1001&pid=2
标签:【无向图最短路】

题目简述

一个卑鄙的食死徒狗蛋得知了学校的秘密就逃跑了。一旦他成功逃脱,学校将陷入极大的危险之中。然而,学校的经理给了你学校的地图,这样你就可以知道他的确切位置。为了简化情况,让我们假设学校只是由房间和走廊组成的。正如你所看到的,走廊太宽敞了,不能隐藏,所以狗蛋不会呆在任何一个走廊里。对于每个走廊,它连接两个房间,长度为x。然而狗蛋很狡猾,他诅咒了你。你只能通过长度为偶数的走廊进入一个房间。在当前的紧急情况下,你必须找出到出口的最短路径。是时候用麻瓜的技术来解决这个问题了。

Input
有𝑇个测试用例,对于每个测试用例,第一行中将有4个整数𝑛,𝑚,𝑠,𝑒,分别表示房间数量,走廊数量,起始房间和出口,接下来的𝑚行中每一行将会有3个整数u,v,w,表示有一条长度为w的走廊连接房间𝑢和𝑣。保证𝑛和m的总和不超过106.

Output
对于每个测试用例,在一行中输出到出口的最短路径的长度。如果没有这样的路径,则输出 -1。

Sample Input

1
4 4 1 4
1 2 1
2 3 1
1 3 6
3 4 2

Sample Output

8

题目思路

无向图的Dijkstra,正反方向存两遍图就行。既然只能走长度为偶数的边,干脆直接在输入时判断,只有是偶数才存进图,否则舍弃。

代码(附注释)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10,M=1e6+10;
const ll inf=0x3f3f3f3f;//初始路径长度

int t,n,m,s,e,fr[N],cnt=0;
int vis[N];//标记数组
ll dis[N];//距离数组
struct Edge{int to,nex,w;}a[M*2];//链式前向星

priority_queue< pair<int,int> >q;//优先队列(利用相反数变成大根堆)

void AddEdge(int x,int y,int z)//存图
{
    a[++cnt]=(Edge){y,fr[x],z};
    fr[x]=cnt;
}

void Dijkstra()
{
    memset(dis,inf,sizeof(dis));//初始化长度和标记
    memset(vis,0,sizeof(vis));

    q.push(make_pair(0,s));//起点入队
    dis[s]=0;
	
    while(!q.empty()){
       int x=q.top().second;
       q.pop();
       if(vis[x]) continue;//已处理过,continue;
       vis[x]=1;
       
       for(int i=fr[x];i;i=a[i].nex){
       	  int y=a[i].to,z=a[i].w;
       	  //cout<<y<<' '<<z<<endl;
       	  if(dis[y]>dis[x]+z){
             dis[y]=dis[x]+z;//松弛
       	     q.push(make_pair(-dis[y],y));//相反数和编号入队
       	  }
       }
    }
}

int main()
{
   ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
   cin>>t;
   while(t--){
	 cin>>n>>m>>s>>e;
   	 memset(fr,0,sizeof(fr));
   	 cnt=0;
   	 for(int i=1;i<=m;i++){
   	     int x,y,z;
	     cin>>x>>y>>z;
             if(z%2==0) AddEdge(x,y,z),AddEdge(y,x,z);//偶数边存入图
          }
   	  Dijkstra();
   	  if(dis[e]!=inf) cout<<dis[e]<<endl;
          else cout<<-1<<endl;
   }

   return 0;
}
posted @ 2021-05-24 09:34  unravel_CAT  阅读(154)  评论(0编辑  收藏  举报