寒假集训日志——图,最短路问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了寒假集训日志——图,最短路问题相关的知识,希望对你有一定的参考价值。

  今天主要学习了图的有关内容,以及DFS,BFS,最短路问题的大致讲解,做了4道习题,完成了今日任务。

  最短路的三种算法:

  1.Dijkstra算法(使用连接矩阵,打起来简单,但是复杂度高)

  2.Bellman Ford算法(松弛操作, 使用较少)

  3.SFPA算法(第一种算法的优化,使用最多)

  另外,求两个点之间的最短路:Floyd算法

  今天做的4道题:

 

A - 最短路
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
Submit Status

Description

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

 

Input

输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商 店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1& lt;=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

我的代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<queue>
using namespace std;

typedef long long ll;
const int N =110 ; 
const int INF = 10e7;
int    cost[N][N] ;

int main()
{
    int n, m; 
    while(cin>>n>>m && ( n!=0 || m!= 0)){
        for( int i = 0 ; i< N ; ++i)
            for( int j = 0 ; j< N; ++j)
                cost[i][j] = 0; 
        for( int i = 1 ; i<=m ; ++i){
            int x, y; 
            cin>>x>>y;
            cin>>cost[x][y];
            cost[y][x] = cost[x][y]; 
        }
        ll lowest[N];
        int flag[N];
        for( int i= 1 ; i<N; ++i){
            lowest[i] = INF ; 
            flag[i] = 0;
        }// initialize
        
        lowest[1] = 0 ;
        
        for( int j= 1 ; j <=n ; ++j){
            int min = INF;
            int k = -1;
            for( int i = 1; i<=n; ++i){
                if( !flag[i] && lowest[i] < min ){
                    min = lowest[i] ; 
                    k = i;
                }
            }
            if( k==-1 ) break;
            flag[k] = 1; 
            
            for( int i = 1; i<=n; ++i){
                if( !flag[i] && cost[k][i]>0 && cost[k][i] + lowest[k] < lowest[i] ){
                    lowest[i] = cost[k][i] + lowest[k];
                } 
            } 
            
        }
        cout<<lowest[n]<<endl;
    } 
    return 0;
}

用的第一种算法。

 

C - Til the Cows Come Home
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
Submit Status

Description

Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before Farmer John wakes her for the morning milking. Bessie needs her beauty sleep, so she wants to get back as quickly as possible.

Farmer John‘s field has N (2 <= N <= 1000) landmarks in it, uniquely numbered 1..N. Landmark 1 is the barn; the apple tree grove in which Bessie stands all day is landmark N. Cows travel in the field using T (1 <= T <= 2000) bidirectional cow-trails of various lengths between the landmarks. Bessie is not confident of her navigation ability, so she always stays on a trail from its start to its end once she starts it.

Given the trails between the landmarks, determine the minimum distance Bessie must walk to get back to the barn. It is guaranteed that some such route exists.

Input

* Line 1: Two integers: T and N

* Lines 2..T+1: Each line describes a trail as three space-separated integers. The first two integers are the landmarks between which the trail travels. The third integer is the length of the trail, range 1..100.

Output

* Line 1: A single integer, the minimum distance that Bessie must travel to get from landmark N to landmark 1.

Sample Input

5 5
1 2 20
2 3 30
3 4 20
4 5 20
1 5 100

Sample Output

90

Hint

INPUT DETAILS:

There are five landmarks.

OUTPUT DETAILS:

Bessie can get home by following trails 4, 3, 2, and 1.
 
我的代码:
#include<iostream>
#include<queue>
#include<cstdio>
#include<vector>

using namespace std;

const int MAXN = 1010;
const int INF = 10e7;
struct Edge{
    int v, cost;

    Edge( int _v, int _cost) : v(_v), cost(_cost){}
};

vector<Edge> E[MAXN];

void addEdge ( int u, int v, int cost){
        E[u].push_back(Edge(v,cost));
}

int main()
{
    int T, N;
    cin>>T>>N;
    for( int i = 0 ; i< T; ++i){
        int a, b, c;
        cin>>a>>b>>c;
        addEdge(a, b, c);
        addEdge(b, a, c);
    }
    //***********INITIALIZE**************//
    int lowest[MAXN], flag[MAXN];
    queue<int> q;
    for( int i = 1; i<=N; ++i){
        lowest[i] = INF;
        flag[i] = 0;
    }
    lowest[N]= 0 ;
    q.push(N) ;     flag[N] = 1;
    //************MAIN*****************//
    while( !q.empty() ){
        int x = q.front() ;     q.pop();
        flag [x] = 0;
        int len = E[x].size();
        for( int i = 0 ; i<len ; ++i){
            int v1= E[x][i].v;
            if( E[x][i].cost> 0 &&lowest[x] + E[x][i].cost < lowest[v1]){
                lowest[ v1 ] = lowest[x] + E[x][i].cost ;
                if( !flag[v1] ){
                    flag[v1] = 1;
                    q.push(v1);
                }
            }
        }
    }
    cout<<lowest[1]<<endl;
    return 0;
    }

用的第三种算法。

 

D - Frogger
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
Submit Status

Description

Freddy Frog is sitting on a stone in the middle of a lake. Suddenly he notices Fiona Frog who is sitting on another stone. He plans to visit her, but since the water is dirty and full of tourists‘ sunscreen, he wants to avoid swimming and instead reach her by jumping.
Unfortunately Fiona‘s stone is out of his jump range. Therefore Freddy considers to use other stones as intermediate stops and reach her by a sequence of several small jumps.
To execute a given sequence of jumps, a frog‘s jump range obviously must be at least as long as the longest jump occuring in the sequence.
The frog distance (humans also call it minimax distance) between two stones therefore is defined as the minimum necessary jump range over all possible paths between the two stones.

You are given the coordinates of Freddy‘s stone, Fiona‘s stone and all other stones in the lake. Your job is to compute the frog distance between Freddy‘s and Fiona‘s stone.

Input

The input will contain one or more test cases. The first line of each test case will contain the number of stones n (2<=n<=200). The next n lines each contain two integers xi,yi (0 <= xi,yi <= 1000) representing the coordinates of stone #i. Stone #1 is Freddy‘s stone, stone #2 is Fiona‘s stone, the other n-2 stones are unoccupied. There‘s a blank line following each test case. Input is terminated by a value of zero (0) for n.

Output

For each test case, print a line saying "Scenario #x" and a line saying "Frog Distance = y" where x is replaced by the test case number (they are numbered from 1) and y is replaced by the appropriate real number, printed to three decimals. Put a blank line after each test case, even after the last one.

Sample Input

2
0 0
3 4

3
17 4
19 4
18 5

0

Sample Output

Scenario #1
Frog Distance = 5.000

Scenario #2
Frog Distance = 1.414

我的代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<cmath>
using namespace std;

const int MAXN = 210 ;

struct Point{
    double x, y;
}pt[MAXN];

double Max ( double a , double b){
    return a>b?a:b;
}
double dis[MAXN][MAXN];

int main()
{
    int n;
    int Case = 0;
    while( cin>>n && n!= 0 ){
        Case ++;
        for( int i = 1 ; i <= n; ++i){
            cin>>pt[i].x>>pt[i].y;
        }
        for( int i = 1; i<= n ; ++i)
            for( int j= 1 ; j<= n ; ++j)
                dis[i][j] = sqrt( (pt[i].x - pt[j].x)*(pt[i].x - pt[j].x) + (pt[i].y - pt[j].y)*(pt[i].y - pt[j].y)) ;

        for( int k = 1; k<= n;  ++k)
            for( int i = 1; i<= n; ++i)
                for( int j = 1; j<= n; ++j){
                    if( dis[i][j] > dis[i][k] && dis[i][j] > dis[k][j] )
                        dis[i][j] = Max( dis[i][k] , dis[k][j]);
                }
        cout<<"Scenario #" <<Case<<endl
        <<"Frog Distance = "<<fixed<<setprecision(3)<<dis[1][2]<<endl;
        cout<<endl;
    }
    return 0 ;
}

用了FLORD算法

 

E - A strange lift
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
Submit Status

Description

There is a strange lift.The lift can stop can at every floor as you want, and there is a number Ki(0 <= Ki <= N) on every floor.The lift have just two buttons: up and down.When you at floor i,if you press the button "UP" , you will go up Ki floor,i.e,you will go to the i+Ki th floor,as the same, if you press the button "DOWN" , you will go down Ki floor,i.e,you will go to the i-Ki th floor. Of course, the lift can‘t go up high than N,and can‘t go down lower than 1. For example, there is a buliding with 5 floors, and k1 = 3, k2 = 3,k3 = 1,k4 = 2, k5 = 5.Begining from the 1 st floor,you can press the button "UP", and you‘ll go up to the 4 th floor,and if you press the button "DOWN", the lift can‘t do it, because it can‘t go down to the -2 th floor,as you know ,the -2 th floor isn‘t exist.
Here comes the problem: when you are on floor A,and you want to go to floor B,how many times at least he has to press the button "UP" or "DOWN"?
 

Input

The input consists of several test cases.,Each test case contains two lines.
The first line contains three integers N ,A,B( 1 <= N,A,B <= 200) which describe above,The second line consist N integers k1,k2,....kn.
A single 0 indicate the end of the input.
 

Output

For each case of the input output a interger, the least times you have to press the button when you on floor A,and you want to go to floor B.If you can‘t reach floor B,printf "-1".
 

Sample Input

5 1 5 3 3 1 2 5 0
 

Sample Output

3
 
我的代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector>
using namespace std;
const int MAXN = 2010;
const int INF = 10e7;
int flag [MAXN];
int lowest[MAXN];
int N, A, B;
bool valid ( int x ){
    if( x >=1 && x<= N)
        return true;
        else return false;
}
int main(){
    while( cin>>N && N!= 0){
        cin>>A>>B;
        //vector <int> arr;
        int arr[MAXN];
        //arr.push_back(0);
        queue <int> q;
        for(int  i = 0 ; i<MAXN ; ++i){
            arr[i] = 0;
        }
        for(int i = 1 ; i<= N ; ++i){
            cin>>arr[i];
        }
       // for( int i = 1 ; i<=N ;++i){
          // int a;
            //cin>>a;
         //   arr.push_back(a);
      //  }
        for( int i = 0 ; i<= MAXN ; ++i){
            flag [i] = 0 ;
            lowest[i]= INF;
        }
        //initialize
        flag[A] = 1 ; lowest[A] = 0;
        q.push(A);
        while( !q.empty()){
            int x = q.front() ;     q.pop();
            flag[x] = 0 ;
            if( valid( x+arr[x]) && lowest[x] + 1 < lowest[ x+arr[x]] ){
                lowest[x + arr[x]] = lowest[x] +1;
                if( flag[x+arr[x]] == 0){
                flag[x + arr[x]]  = 1;
                q.push(x +arr[x]) ;
                }
            }
            if( valid( x-arr[x]) && lowest[x] + 1 < lowest[ x-arr[x]] ){
                lowest[x - arr[x]] = lowest[x] +1;
                if( flag[x-arr[x]] == 0){
                flag[x - arr[x]]  = 1;
                q.push(x -arr[x]) ;
                }
            }
        }
        if( lowest[B] != INF)
            cout<< lowest[B]<<endl;
            else cout<<-1<<endl;
    }
    return 0;
}

用了第三种算法

今天觉的很有收获,继续加油!!!

以上是关于寒假集训日志——图,最短路问题的主要内容,如果未能解决你的问题,请参考以下文章

(寒假集训) Piggyback(最短路)

(寒假集训)Roadblock(最短路)

寒假集训日志——期中测验

寒假集训日志——最小生成树,拓扑排序,欧拉回路,连通路

寒假集训第六天---LCA题解

寒假集训日志——DP