用vector 加 pair存图

前面已经简单的介绍了vector和  pair,目的就是这一章,那就是利用二者去存一些正常的二维数组存不了的图。例如点的个数大于5000的时候,你再用二维数组去存的话,根本不行的,因为内存不允许,这个时候就轮到vector出马了。

我们可以定义一个这样的vector:

vector<pair<int,int> > A[maxn];假如有一个1这个点到2这个点的边,且长度为10,我们便可以把这条边给存储才来,记成:vector<pair<2,10> > A[1],这样我们就把这样的一条边给存储了才来。

下面我们给一道题:牛客上面的一道题。

链接:https://www.nowcoder.com/acm/contest/181/D
来源:牛客网
 

小叶的巡查

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 65536K,其他语言131072K
64bit IO Format: %lld

题目描述

8102年,牛客系列竞赛空前繁荣。为了更好地管理竞赛,小叶决定巡查于各大城市之间,体察民情。所以,从一个城市马不停蹄地到另一个城市成了小叶最常做的事情。小叶有一个钱袋,用于存放往来城市间的路费。

这个国家有一套优秀的交通方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。

如果不在某个城市停下来修整,在连续行进过程中,小叶所花的路费与他已走过的距离有关,在走第x-1千米到第x千米这一千米中(x是整数),他花费的路费是x+10这么多。也就是说走1千米花费11,走2千米要花费23。

因为国家力挺牛客系列竞赛,所以国家会给小叶报销全部的路费。

现在组织想知道:小叶从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?

输入描述:

输入的第一行包含一个整数n,表示包括首都在内的城市数
城市从1开始依次编号,1号城市为首都。
接下来n-1行,描述高速路(高速路一定是n-1条)
每行三个整数Pi, Qi, Di,表示城市Pi和城市Qi之间有一条高速路,长度为Di千米。

输出描述:

输出一个整数,表示小叶最多花费的路费是多少。

示例1

输入

复制

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

输出

复制

135

备注:

n<23333

 这道题其实也很简单就是用两次BFS求一下树的直径就行了,但这题的关键就是存图,这题的n是23333,已经远远超过了5000了,所以用正常的二维数组去存,那是根本放不下的,所以这个时候就要轮到vector和pair出马了。

假如我们先定义一个二维数组,vector<pair<int,int> > A[maxn]。现在你给你一个a到b之间有一个长度为c的路径,那么你怎么把这条路径给存下来呢?其实也很简单

        A[a].push_back(make_pair(b,c));
        A[b].push_back(make_pair(a,c));

这两行代码就把这一条边给存储下来了,为什么是两行呢?因为这是一个无向图。

图存好之后接下来就是访问这个图了?那么问题来了,我们该怎么访问呢?

首先我们先要明确一个概念,就是A[F].size(),这是什么意思呢,就是以F为起点的边有几个。

我们再来看下一个,就是A[F][i],知道这个二维数组代表的什么意思吗?我们还是先回到刚开始的时候吧,就是我们的定义vector<pair<int,int> > A[maxn],这个二维数组到底该怎么理解呢?其实我是这样理解的,我也不知道对不对,就是 pair是一个整体,A[0][0],就是第1行的第一个pair,也就是说A[0][0]这里面存的是一个pair类型的变量。

也就是说A[f][i],就是第f-1行的第i个pair,如果我们能够把这个理解,那么其他的也就非常的好说了,

下面给出这道题的AC代码,我再从代码入手,好好地讲解一下上面所说的东西。

#include<stdio.h>
#include<string.h>
#include<queue>
#include<vector>
using namespace std;
const int maxn=24000;
int vis[maxn];//把走过的点进行标记
int dis[maxn];//到达每个点所需要走的路径长度。

vector<pair<int,int> >A[maxn];
long long ans=0;;
int point;
void bfs(int x)
{
    memset(vis,0,sizeof(vis));
    memset(dis,0,sizeof(dis));
    queue<int> que;
    que.push(x);
    vis[x]=1;
    while(!que.empty())
    {
        int f=que.front();
        que.pop();
        if(dis[f]>ans)
        {
            ans=dis[f];
            point=f;
        }
        pair<int,int> p;
        for(int i=0;i<A[f].size();i++)//开始搜索以f为起点的所有的pair
        {
            p=A[f][i];                 //这一行是不是更能证明A[x][y]这个二维数组指向的就是一个pair;
            if(vis[p.first]==0)          //如果这个点没有走过则接着走。
            {
                vis[p.first]=1;           //标记这个点。
                dis[p.first]=dis[f]+p.second;//p.first代表一条边的中点,p.second代表这条边的权值。
                que.push(p.first);

            }
        }

    }
}
int main()
{
    int n;
    scanf("%d",&n);
    n--;
    while(n--)
    {
        int a,b,c;
        scanf("%d %d %d",&a,&b,&c);
        A[a].push_back(make_pair(b,c));
        A[b].push_back(make_pair(a,c));//建图
    }
    bfs(1);
    ans=0;
    bfs(point);//两次bfs求树的直径
    ans=ans*(ans+1)/2+ans*10;
    printf("%lld\n",ans);
    return 0;
}







猜你喜欢

转载自blog.csdn.net/qq_42757965/article/details/82383293