※NC14550 旅行

太菜了。。。这么简单的模型都看不出来。。。

模型:图的直径

注意:原题为无向图

暴力思路:从\(1000\)个点中选取\(3\)个点的排列,然后求路径和。

上述思路过于暴力,我们知道\(dijkstra\)算法求得的\(dist\)数组是源点\(s\)到其余点的最短距离

我们只需将源点看成中转点,然后求出当前点到其余点的最大距离和次大距离(这里的距离均指最短距离)。

无解情况:只要存在大于等于\(3\)个点的连通块就是有解的,如果只有小于等于\(2\)个点的连通块,次大值一定为\(0\)(因为两个点只会更新一次距离,一个点没有邻点更新距离)

const int N=1010;
vector<PII> g[N];
int dist[N];
bool vis[N];
int n,m;

int dijkstra(int s)
{
    memset(dist,0x3f,sizeof dist);
    memset(vis,0,sizeof vis);
    priority_queue<PII,vector<PII>,greater<PII> > heap;
    dist[s]=0;
    heap.push({0,s});

    int one=0,two=0;
    while(heap.size())
    {
        int dis=heap.top().fi,t=heap.top().se;
        heap.pop();

        if(vis[t]) continue;
        vis[t]=true;

        if(dis > one) two=one,one=dis;
        else if(dis > two) two=dis;

        for(int i=0;i<g[t].size();i++)
        {
            int j=g[t][i].fi,w=g[t][i].se;
            if(dist[j] > dist[t]+w)
            {
                dist[j]=dist[t]+w;
                heap.push({dist[j],j});
            }
        }
    }

    if(!two) return 0;
    return one+two;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n>>m;

        for(int i=1;i<=n;i++) g[i].clear();

        while(m--)
        {
            int a,b,c;
            cin>>a>>b>>c;
            g[a].pb({b,c});
            g[b].pb({a,c});
        }

        int res=0;
        for(int i=1;i<=n;i++) res=max(res,dijkstra(i));
        if(!res) puts("-1");
        else cout<<res<<endl;
    }

    //system("pause");
}
原文地址:https://www.cnblogs.com/fxh0707/p/13768245.html