hdu-5521-Meeting- 最短路-增点建图

http://acm.hdu.edu.cn/showproblem.php?pid=5521

题目意思就是给你一个图,n个城市,求 1和n相遇的最短距离,显然就是分别以1和n出发求一次最短路,答案就是 min【max( dis1[i],disn[i] )】


...但是本题给的图很特别,直接给出m个集合,每个集合里有k个点,集合内任意两点之间的边权是t。

显然不能暴力n^2建图,否则极端情况就会挂。


我们可以通过 借助一个  不存在的节点来建图:

对每个集合 new一个点n+i,联通集合内所有点的,花费为t。


这样就使得集合内所有点联通,只不过实际计算的边权为2t。没关系,我们直接在输出答案的时候把答案除二即可。


这样使得图的最大节点为 n*2,其余地方和正常最短路无异咯

跑了2S

//poj2387  --求n到1最短路
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
struct node
{
    int x,v;
    node() {}
    node(int a,int b)
    {
        x=a;
        v=b;
    }
    bool operator <(const node&b) const
    {
        return v>b.v;					//*****
    }
};
vector<node> mp[200050];

int dist1[200005];
int dist2[200005];     //n到其他点的最短路
const int inf=2147483647;
priority_queue<node> qq;
int st;
int n,m;
int main()
{
    int t;
    cin>>t;
    void dji(int []);
    int cnt=1;
    while(t--)
    {
        int i,j;
        int a,b,c;
        cin>>n>>m;
        for (i=1; i<=2*n; i++) mp[i].clear();

        int idx=n;
        for (i=1; i<=m; i++)
        {
            idx++;
            int tt,kk,x;
            scanf("%d%d",&tt,&kk);

            for (j=1; j<=kk; j++)
            {
                scanf("%d",&x);
                mp[idx].push_back(node(x,tt));
                mp[x].push_back(node(idx,tt));
            }
        }
        int tmpn=n;
        n=idx;

        st=1;
        dji(dist1);
        st=tmpn;
        dji(dist2);
        int minn=inf;
        printf("Case #%d: ",cnt++);
        // for (i=1;i<=tmpn;i++) dist1[i]/=2,dist2[i]/=2;

        for (i=1; i<=tmpn; i++)
        {
            minn=min(minn,max(dist1[i],dist2[i]));
        }
        if (dist1[tmpn]==inf)
            printf("Evil John\n");
        else
        {
            printf("%d\n",minn/2);  //实际答案除二哦
            int line=0;
            for (i=1; i<=tmpn; i++)
            {
                if(max(dist1[i],dist2[i])==minn)
                {

                    if (line)  printf(" ");
                    printf("%d",i);
                    line=1;
                }
            }
            printf("\n");
        }
    }
    return 0;
}

void dji(int dist[])
{
    while(!qq.empty())  qq.pop();
    int i;
    int vis[200005];
    for (i=1; i<=n; i++)
    {
        dist[i]=inf;
        vis[i]=0;
    }
    dist[st]=0;
    node sst(st,0);
    qq.push(sst);

    while(!qq.empty())
    {
        node t=qq.top();
        qq.pop();
        int num=t.x;
        if (vis[num]) continue;
        vis[num]=1;
        for (i=0; i<mp[num].size(); i++)
        {
            node tmp=mp[num][i];
            int x=tmp.x;
            int v=tmp.v;

            if (!vis[x]&&v+dist[num]<dist[x])
            {
                dist[x]=v+dist[num];
                node np(x,dist[x]);
                qq.push(np);
            }
        }
    }

}


你可能感兴趣的:(hdu-5521-Meeting- 最短路-增点建图)