NYOJ 711 最舒适的路线(bfs+优先队列)

最舒适的路线

时间限制:5000 ms  |  内存限制:65535 KB
难度:5
描述

异形卵潜伏在某区域的一个神经网络中。其网络共有N个神经元(编号为1,2,3,…,N),这些神经元由M条通道连接着。两个神经元之间可能有多条通道。异形卵可以在这些通道上来回游动,但在神经网络中任一条通道的游动速度必须是一定的。当然异形卵不希望从一条通道游动到另一条通道速度变化太大,否则它会很不舒服。

现在异形卵聚居在神经元S点,想游动到神经元T点。它希望选择一条游动过程中通道最大速度与最小速度比尽可能小的路线,也就是所谓最舒适的路线。

输入
第一行: K 表示有多少组测试数据。 
接下来对每组测试数据:
第1行: N M
第2~M+1行: Xi Yi Vi (i=1,…..,M)
表示神经元Xi 到神经元Yi之间通道的速度必须是Vi
最后一行: S T ( S  T )

【约束条件】
2≤K≤5 1<N≤500 0<M≤5000 1≤ Xi, Yi , S , T ≤N 0< Vi <30000,
Vi是整数。数据之间有一个空格。
输出
对于每组测试数据,输出一行:如果神经元S到神经元T没有路线,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。
样例输入
2
3 2
1 2 2
2 3 4
1 3
3 3
1 2 10
1 2 5
2 3 8
1 3
样例输出
2
5/4
思路:一道广搜题,注意题目中说的 “两个节点间可以有多条通道” ,还有就是S==T的情况。。

注意下面一组数据:
10
3 3
1 2 1
1 2 2
2 3 3
1 3

代码:
#include<stdio.h>
#include<string.h>
#include<vector>
#include<math.h>
#include<queue>
#define INF 1e9
#define Max(a,b) a>b?a:b
#define Min(a,b) a>b?b:a 
using namespace std;
struct Node
{
  int pre; //记录前一位置 
  int pos;
  int max,min;
  int val;
  double p;	
  Node(){}
  Node(int _pos,int _val,int _max,int _min)
  {
  	pos=_pos;
  	val=_val;
  	max=_max;
  	min=_min;
  }
  friend bool operator<(Node a,Node b)
  {
  	return a.p>b.p;
  }
}; 
int n,m;
int S,T;
//double P;
int vis[505][505];
vector<Node> map[505];
int gcd(int a,int b)
{
	if(a%b==0) return b;
	return gcd(b,a%b);
}
void bfs()
{
	priority_queue<Node> q;//优先队列,p值小的优先级高 
	Node node;
	node.pos=S;
	node.max=-INF;
	node.min=INF;
	node.pre=S;
	q.push(node);
	while(!q.empty())
	{
		node=q.top();
		q.pop();
		int pos=node.pos;
		int max=node.max;
		int min=node.min;
		int val=node.val;
		int pre=node.pre;
		double p=node.p;
//		printf("pos=%d max=%d min=%d p=%.4lf\n",pos,max,min,p);
		if(pos==T)
		{
		//	if(P>p) P=p;
		    if(p>floor(p))//floor(p)对p四舍五入取整 
		    {
		    	int r=gcd(max,min);
		    	printf("%d/%d\n",max/r,min/r);
			}
			else  printf("%.lf\n",p);
		   // printf("P==%.4lf  p==%.4lf\n",P,p);
			break;
			//continue ;
		}
		if(vis[pos][pre]>0)  //删除与前一节点相连接的边 
		{
		   vis[pos][pre]--;
		   vis[pre][pos]--;
		}
		for(int i=0;i<map[node.pos].size();i++)
		{
			Node temp=map[node.pos][i];
			if(!vis[pos][temp.pos]) continue ;
//			printf("temp.val=%d \n",temp.val);
			temp.max=Max(temp.val,max);
			temp.min=Min(temp.val,min);
//			printf("temp.max=%d temp.min=%d\n",temp.max,temp.min);
			temp.p=(double)temp.max/temp.min;
			temp.pre=pos;//记录前一节点 
			q.push(temp);
		}
	}
}
int main()
{//printf("%d",gcd(5,15));
	int t;
	scanf("%d",&t);
	while(t--)
	{
		memset(vis,false,sizeof(vis));
		memset(map,0,sizeof(map));
		scanf("%d%d",&n,&m);
		for(int i=0;i<m;i++)
		{
			int a,b,v;
			scanf("%d %d %d",&a,&b,&v);
			vis[a][b]++;
			vis[b][a]++;
			map[a].push_back(Node(b,v,-INF,INF));
			map[b].push_back(Node(a,v,-INF,INF));
		}
		scanf("%d %d",&S,&T);
		if(S==T)
		{
			printf("1\n");
			continue ;
		}
//		P=INF;
		bfs();
		
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值