2021-1-30最短路入门

首先贴一篇文章 讲的特别好最短路的三种算法(Floyd、Dijkstra、SPFA)


A-最短路

在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?

Input

输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
输入保证至少存在1条商店到赛场的路线。

Output

对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间

Sample Input

2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0

Sample Output

3
2

題解:
Dijkstra的模板題

#include<iostream>
using namespace std;
int map[105][105],dis[105],vis[105];
int n,m,u,v,t;
#define INF 0x3f3f3f3f

void Dijkstra(int src){
    
    
	for(int i=1;i<=n;i++){
    
    //初始化所有点到起点的最小距离 
		dis[i]=map[src][i];
		vis[i]=0;
	}
	vis[src]=1;
	for(int i=1;i<=n;i++){
    
    
		int ans=INF,k;
		for(int j=1;j<=n;j++){
    
    
			if(!vis[j]&&dis[j]<ans){
    
    //寻找未被访问过但是离起点最近的点 
				k=j;
				ans=dis[j];
			}
		}
		vis[k]=1;//标记已经被访问过
		if(ans==INF)break;//剩下的点都不通
		
		//下面的是松弛操作 
		for(int j=1;j<=n;j++){
    
    
			if(!vis[j]&&dis[k]+map[j][k]<dis[j]){
    
    
				dis[j]=map[j][k]+dis[k];
			}
		} 
	}
	printf("%d\n",dis[n]);
}

int main(){
    
    
	while(~scanf("%d %d",&n,&m)){
    
    
		if(n==0&&m==0)break;
		
		//下面是初始化 
		for(int i=1;i<=n;i++){
    
    
			for(int j=1;j<=n;j++){
    
    
				if(i==j)map[i][j]=0;//自己到自己的距离
				else map[i][j]=INF;//初始化到无穷大 
			}
		}
		
		for(int i=1;i<=m;i++){
    
    
			scanf("%d %d %d",&u,&v,&t);
			if(t<map[u][v])map[u][v]=map[v][u]=t;//更新保持map数组储存两地最小距离 
		}
		
	    Dijkstra(1);
	}
	return 0;
} 

B題和C題都是Dijkstra的模板題,就略了。
就是要仔細看樣例的數據。C題看錯數據,還以爲自己做錯了,手打了3遍代碼,難受

要注意的是,要分清方向是單向還是雙向


D - Heavy Transportation

Background
Hugo Heavy is happy. After the breakdown of the Cargolifter project he can now expand business. But he needs a clever man who tells him whether there really is a way from the place his customer has build his giant steel crane to the place where it is needed on which all streets can carry the weight.
Fortunately he already has a plan of the city with all streets and bridges and all the allowed weights.Unfortunately he has no idea how to find the the maximum weight capacity in order to tell his customer how heavy the crane may become. But you surely know.

Problem
You are given the plan of the city, described by the streets (with weight limits) between the crossings, which are numbered from 1 to n. Your task is to find the maximum weight that can be transported from crossing 1 (Hugo’s place) to crossing n (the customer’s place). You may assume that there is at least one path. All streets can be travelled in both directions.

Input

The first line contains the number of scenarios (city plans). For each city the number n of street crossings (1 <= n <= 1000) and number m of streets are given on the first line. The following m lines contain triples of integers specifying start and end crossing of the street and the maximum allowed weight, which is positive and not larger than 1000000. There will be at most one street between each pair of crossings.

Output

The output for every scenario begins with a line containing “Scenario #i:”, where i is the number of the scenario starting at 1. Then print a single line containing the maximum allowed weight that Hugo can transport to the customer. Terminate the output for the scenario with a blank line.

Sample Input

1
3 3
1 2 3
1 3 4
2 3 5

Sample Output

Scenario #1:
4

大致題意:
有T組測試數據,對於每組數據,有n個地點,和m條道路。每條道路都有最大載重量。求出從1到n的最大載重量。

題解:
也可以用Dijkstra的模板來做,但是要把關係改成max和min

格式問題也要注意一下

#include<cstring>
#include<iostream>
#define INF 0x3f3f3f3f
using namespace std;
int map[1010][1010],dis[1010];
bool vis[1010];
int n,m,T,u,v,t;
void Dijkstra(){
    
    
    for(int i=1;i<=n;i++){
    
    
        dis[i]=map[1][i];
        vis[i]=0;
    }
    for(int i=1;i<=n;i++){
    
    
        int max=-INF,x;
        for(int j=1; j<=n; j++)
            if(!vis[j]&&dis[j]>max) {
    
    max=dis[j];x=j;}
        vis[x]=1;
        for(int j=1; j<=n; j++)
            if(!vis[j]&&dis[j]<min(dis[x],map[x][j]))
                dis[j]=min(dis[x],map[x][j]);
    }
}
int main(){
    
    
    scanf("%d",&T);
    for(int cnt=1;cnt<=T;cnt++){
    
    
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n; i++)
            for(int j=1;j<=n;j++){
    
    
            	if(i==j)map[i][j]=0;
            	else map[i][j]=-INF;
			}
                
                
        for(int i=1;i<=m;i++){
    
    
            scanf("%d %d %d",&u,&v,&t);
            if(map[u][v]<t)
                map[u][v]=map[v][u]=t;
        }
        Dijkstra();
        printf("Scenario #%d:\n%d\n\n",cnt,dis[n]);
    }
}

E - Cow Contest

N (1 ≤ N ≤ 100) cows, conveniently numbered 1…N, are participating in a programming contest. As we all know, some cows code better than others. Each cow has a certain constant skill rating that is unique among the competitors.

The contest is conducted in several head-to-head rounds, each between two cows. If cow A has a greater skill level than cow B (1 ≤ A ≤ N; 1 ≤ B ≤ N; A ≠ B), then cow A will always beat cow B.

Farmer John is trying to rank the cows by skill level. Given a list the results of M (1 ≤ M ≤ 4,500) two-cow rounds, determine the number of cows whose ranks can be precisely determined from the results. It is guaranteed that the results of the rounds will not be contradictory.

Input

  • Line 1: Two space-separated integers: N and M
  • Lines 2…M+1: Each line contains two space-separated integers that describe the competitors and results (the first integer, A, is the winner) of a single round of competition: A and B

Output

  • Line 1: A single integer representing the number of cows whose ranks can be determined

Sample Input

5 5
4 3
4 2
3 2
1 2
2 5

Sample Output

2

大致題意:
對於每組數據,有n頭奶牛和m個勝負關係。接下來2-m+1行,輸入a打敗了b的關係。輸出可以得出排名關係的奶牛數量

題解:
首先肯定是要輸入給出的關係的,然後用Floyd函數更新一下可以傳遞得出的關係,那麽有n-1個關係(除了和自己,知道有沒有戰勝全部別的奶牛)就是題目要求的奶牛,算出數量即可

#include<cstring>
#include<iostream>
#define INF 0x3f3f3f3f
using namespace std;
int map[1010][1010],dis[1010];
bool vis[1010];
int n,m,T,u,v,t;
void Dijkstra(){
    
    
    for(int i=1;i<=n;i++){
    
    
        dis[i]=map[1][i];
        vis[i]=0;
    }
    for(int i=1;i<=n;i++){
    
    
        int max=-INF,x;
        for(int j=1; j<=n; j++)
            if(!vis[j]&&dis[j]>max) {
    
    max=dis[j];x=j;}
        vis[x]=1;
        for(int j=1; j<=n; j++)
            if(!vis[j]&&dis[j]<min(dis[x],map[x][j]))
                dis[j]=min(dis[x],map[x][j]);
    }
}
int main(){
    
    
    scanf("%d",&T);
    for(int cnt=1;cnt<=T;cnt++){
    
    
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n; i++)
            for(int j=1;j<=n;j++){
    
    
            	if(i==j)map[i][j]=0;
            	else map[i][j]=-INF;
			}
                
                
        for(int i=1;i<=m;i++){
    
    
            scanf("%d %d %d",&u,&v,&t);
            if(map[u][v]<t)
                map[u][v]=map[v][u]=t;
        }
        Dijkstra();
        printf("Scenario #%d:\n%d\n\n",cnt,dis[n]);
    }
}

猜你喜欢

转载自blog.csdn.net/m0_52433146/article/details/113445684
今日推荐