图论南阳155题 城市平乱

思路:刚开始用了佛洛伊德算法,没想到超时了。后来改用多次迪杰斯特算法就过了。

迪杰斯特算法是求出源点到其余点的最短距离 这里是求出队伍到危险去的距离然后找出最小的那个然后输出就ok了,注意他说两个城市之间可能有多条路径此时我们要选一条最小的路;

城市平乱

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 4
描述

南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市。

他在用这N个部队维护着M个城市的治安,这M个城市分别编号从1到M。

现在,小工军师告诉南将军,第K号城市发生了暴乱,南将军从各个部队都派遣了一个分队沿最近路去往暴乱城市平乱。

现在已知在任意两个城市之间的路行军所需的时间,你作为南将军麾下最厉害的程序员,请你编写一个程序来告诉南将军第一个分队到达叛乱城市所需的时间。

注意,两个城市之间可能不只一条路。

输入
第一行输入一个整数T,表示测试数据的组数。(T<20)
每组测试数据的第一行是四个整数N,M,P,Q(1<=N<=100,N<=M<=1000,M-1<=P<=100000)其中N表示部队数,M表示城市数,P表示城市之间的路的条数,Q表示发生暴乱的城市编号。
随后的一行是N个整数,表示部队所在城市的编号。
再之后的P行,每行有三个正整数,a,b,t(1<=a,b<=M,1<=t<=100),表示a,b之间的路如果行军需要用时为t

数据保证暴乱的城市是可达的。
输出
对于每组测试数据,输出第一支部队到达叛乱城市时的时间。每组输出占一行
样例输入
1
3 8 9 8
1 2 3
1 2 1
2 3 2
1 4 2
2 5 3
3 6 2
4 7 1
5 7 3
5 8 2
6 8 2 
样例输出
4
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define max 1010
#define wqd  0x7fffffff  
int map[max][max];
typedef struct Graph
{
	 //邻接表 
	int n;//顶点数目 
	int e; //边数目 
}graph;
graph mgraph;int d[1001],path[1001],budui[101];
bool dijst(graph mgraph,int *d,int *p,int v0)//d[i]表示i到v0的最短距离,p是用来保存最短路径的这里不用
{
	bool *vis=(bool*)malloc(sizeof(bool) * (mgraph.n+1));
	for(int i=1;i<=mgraph.n;i++)//赋初值
	{
		if(i!=v0&&map[v0][i]!=0)
		{
			d[i]=map[v0][i];
			p[i]=v0; 
		} 
		else 
		{
			d[i]=wqd;
			p[i]=-1;
		}
		vis[i]=0;
	}
	d[v0]=0;
	p[v0]=0;
	vis[v0]=1;//扩展n次
for(int j=1;j<=mgraph.n;j++)
{
	 int min=wqd,u;

	for(int i=1;i<=mgraph.n;i++)//找最小的边
	{
		if(!vis[i]&&d[i]<min)
		{
			min=d[i];
			u=i;
		}
	}
	vis[u]=1;
	for(int i=1;i<=mgraph.n;i++)//看看有没有点经过这条最小的边比原来的距离更加短
	{
		if(!vis[i]&&d[u]+map[u][i]<d[i]&&map[u][i]!=0)
		{
			d[i]=d[u]+map[u][i];
			p[i]=u;
		}
	}
}
} 

int main()
{
    int m,n,t;
    int x,y,z;
    scanf("%d",&t);
   while( t--)
    {int p,q;
      scanf("%d%d%d%d",&n,&m,&p,&q);
      mgraph.e=p;
      mgraph.n=m;
      memset(map,0,sizeof(map));
      for(int i=1;i<=n;i++)
      {
      	scanf("%d",&budui[i]);	
      }
      memset(d,max,sizeof(d));
      for(int i=1;i<=p;i++)
      {
      	int x,y,w;
      	scanf("%d%d%d",&x,&y,&w);
      	if(map[x][y]==0) map[x][y]=w,map[y][x]=w;
      	 else if(map[x][y]>w) map[x][y]=map[y][x]=w;//可能有多条路,用最小的那一条
      	
      }int min=wqd;
      for(int i=1;i<=n;i++)
      {
      	memset(d,0,sizeof(d));//依次求出队伍到目标地的最短时间
      	 dijst( mgraph,d,path,budui[i]);
      	 
      	 
      	 if(min>d[q]) min=d[q];找出最小的输出
      	
      }
      printf("%d\n",min);
    /*    for(int i=1;i<=m;i++)
           {
               for(int j=1;j<=m;j++)
			      printf("%d-%d=%d ",i,j,d[i][j]);
			   }
   
    for(int i=1;i<=n;i++)
    {
    	if(min>d[budui[i]][q]) min=d[budui[i]][q];
    }
    printf("%d\n",min);*/
    
}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值