ccf 地铁修建spfa (得分85到100)

版权声明:欢迎转载!拒绝抄袭. https://blog.csdn.net/qq_36257146/article/details/82142745

问题描述

  A市有n个交通枢纽,其中1号和n号非常重要,为了加强运输能力,A市决定在1号到n号枢纽间修建一条地铁。
  地铁由很多段隧道组成,每段隧道连接两个交通枢纽。经过勘探,有m段隧道作为候选,两个交通枢纽之间最多只有一条候选的隧道,没有隧道两端连接着同一个交通枢纽。
  现在有n家隧道施工的公司,每段候选的隧道只能由一个公司施工,每家公司施工需要的天数一致。而每家公司最多只能修建一条候选隧道。所有公司同时开始施工。
  作为项目负责人,你获得了候选隧道的信息,现在你可以按自己的想法选择一部分隧道进行施工,请问修建整条地铁最少需要多少天。

输入格式

  输入的第一行包含两个整数nm,用一个空格分隔,分别表示交通枢纽的数量和候选隧道的数量。
  第2行到第m+1行,每行包含三个整数abc,表示枢纽a和枢纽b之间可以修建一条隧道,需要的时间为c天。

输出格式

  输出一个整数,修建整条地铁线路最少需要的天数。

样例输入

6 6
1 2 4
2 3 4
3 6 7
1 4 2
4 5 5
5 6 6

样例输出

6

样例说明

  可以修建的线路有两种。
  第一种经过的枢纽依次为1, 2, 3, 6,所需要的时间分别是4, 4, 7,则整条地铁线需要7天修完;
  第二种经过的枢纽依次为1, 4, 5, 6,所需要的时间分别是2, 5, 6,则整条地铁线需要6天修完。
  第二种方案所用的天数更少。

评测用例规模与约定

  对于20%的评测用例,1 ≤ n ≤ 10,1 ≤ m ≤ 20;
  对于40%的评测用例,1 ≤ n ≤ 100,1 ≤ m ≤ 1000;
  对于60%的评测用例,1 ≤ n ≤ 1000,1 ≤ m ≤ 10000,1 ≤ c ≤ 1000;
  对于80%的评测用例,1 ≤ n ≤ 10000,1 ≤ m ≤ 100000;
  对于100%的评测用例,1 ≤ n ≤ 100000,1 ≤ m ≤ 200000,1 ≤ ab ≤ n,1 ≤ c ≤ 1000000。

  所有评测用例保证在所有候选隧道都修通时1号枢纽可以通过隧道到达其他所有枢纽。

这道题的关键是1->n的路径中会有很多条边,其中最长的边的长度就是开工的总天数,那么自然是这条边越短越好.一开始没有理解题意,结果求成了最短路径...其实是本人太水...

后来把条件给改了一下,基本上是如果新加入的边有更短的话就更新,然后运行超时...不知道还有什么方法可以改进....

O(∩_∩)O哈哈~

#include <iostream>
#include <map>
#include <string.h>
#include <vector>
#include <cmath>
#include <queue>
#define maxn 100001
#define inf 0x3f3f3f3f
using namespace std;
int n;
int dis[maxn];
int vis[maxn];

struct Node
{
    int des;
    int far;
};

vector<Node>site[maxn];
void print();

int findFar(int v,int w)
{
    for(int i = 0; i<site[v].size(); i++)
    {
        if(site[v][i].des == w)
        {
            return site[v][i].far;
        }

    }
    return -1;
}

void spfa(int v)
{
    queue<int>st;
    st.push(v);
    dis[v] = 0;
    vis[v] = 1;//已经被访问过
    while(!st.empty())
    {
        int u = st.front();
        st.pop();
        vis[u] = 0;
        int flag = 0;
        for(int i =0; i<site[u].size(); i++)
        {
            int w = site[u][i].des;
            if(dis[w]>max(dis[u],findFar(u,w)))
            {
                dis[w] = max(dis[u],findFar(u,w));
                flag = 1;
            }
            if(flag&&!vis[w])
            {
                st.push(w);
                vis[w] = 1;
            }
        }

    }

}

void print()
{
    for(int i = 1; i<=n; i++)
    {
        for(int j = 1; j<=n; j++)
        {
            if(findFar(i,j)==-1)
                cout<<"inf";
            else
                cout<<findFar(i,j);
            cout<<" ";
        }
        cout<<endl;
    }
    cout<<endl;

}

int main()
{
    int m;
    cin>>n>>m;
    Node node;
    int a,b,c;
    for(int i = 1; i<=m; i++)
    {
        cin>>a>>b>>c;
        if(a!=b)
        {
            node.des = b;
            node.far = c;
            site[a].push_back(node);
            node.des = a;
            site[b].push_back(node); 
        }
            
        
    }
    memset(dis,inf,sizeof(dis));//初始化为无穷大
    memset(vis,0,sizeof(vis));
    spfa(1);
    cout<<dis[n];
    return 0;
}
/*
6 6
1 2 4
2 3 4
3 6 7
1 4 2
4 5 5
5 6 6
*/

天啦,后面看了一个大佬的文章,把cin>>a>>b>>c改成scanf,得了95分

然后又把spfa()中的flag去掉,直接在更新条件里面判断是否加入队列就!100!了!!!

#include <iostream>
#include <cstdio>
#include <map>
#include <string.h>
#include <vector>
#include <cmath>
#include <queue>
#define maxn 100001
#define inf 0x3f3f3f3f
using namespace std;
int n;
int dis[maxn];
int vis[maxn];

struct Node
{
    int des;
    int far;
};

vector<Node>site[maxn];

void spfa(int v)
{
    queue<int>st;
    st.push(v);
    dis[v] = 0;
    vis[v] = 1;//已经被访问过
    while(!st.empty())
    {
        int u = st.front();
        st.pop();
        vis[u] = 0;
        for(int i =0; i<site[u].size(); i++)
        {
            int w = site[u][i].des;
            if(dis[w]>max(dis[u],site[u][i].far))
            {
                dis[w] = max(dis[u],site[u][i].far);
                if(!vis[w])
                {
                    st.push(w);
                    vis[w] = 1;
                }
            }
        }

    }

}

int main()
{
    int m;
    cin>>n>>m;
    Node node;
    int a,b,c;
    for(int i = 1; i<=m; i++)
    {
        //cin>>a>>b>>c;
        scanf("%d%d%d",&a,&b,&c);
        if(a!=b)
        {
            node.des = b;
            node.far = c;
            site[a].push_back(node);
            node.des = a;
            site[b].push_back(node);
        }


    }
    memset(dis,inf,sizeof(dis));//初始化为无穷大
    memset(vis,0,sizeof(vis));
    spfa(1);
    cout<<dis[n];
    return 0;
}
/*
6 6
1 2 4
2 3 4
3 6 7
1 4 2
4 5 5
5 6 6
*/

大佬的文章在这里:

https://blog.csdn.net/qq_40400202/article/details/80904621

嗯...一道水题花了这么长时间,看来还有很长一段路要走啊啊啊

猜你喜欢

转载自blog.csdn.net/qq_36257146/article/details/82142745