※P1119 灾后重建

\(TLE\)代码

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

int dijkstra(int st,int ed,int limit)
{
    if(tim[st]>limit || tim[ed]>limit) return -1;

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

    while(heap.size())
    {
        int t=heap.top().second;
        heap.pop();

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

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

    if(dist[ed] == INF) return -1;
    return dist[ed];
}

int main()
{
    cin>>n>>m;

    for(int i=0;i<n;i++) cin>>tim[i];

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

    cin>>q;
    while(q--)
    {
        int x,y,t;
        cin>>x>>y>>t;
        cout<<dijkstra(x,y,t)<<endl;
    }
    //system("pause");
}

注意输入条件

  • \(第二行包含N个非负整数t_0, t_1,…, t_{N-1},表示了每个村庄重建完成的时间,数据保证了t_0 ≤ t_1 ≤ … ≤ t_{N-1}\)

即每个村庄的重建完成时间按村庄编号递增

观察到数据范围

  • \(N≤200\),不免联想到\(O(n^3)\)的最短路floyd算法

floyd算法本质:动态规划,d[k,i,j]表示从i号顶点到j号顶点只经过前k号点的最短距离

我们再回头看题意:

所有的边全部给出,按照时间顺序更新每一个可用的点(即修建好村庄),对于每个时间点进行两点之间询问,求对于目前建设的所有村庄来说任意两点之间的最短路。

不正好就是Floyd算法中使用前k个节点更新最短路的思维吗?

出题人还是很良心的,保证所有的数据都是用时间顺序给出的,所以我们只用读取+操作就可以了,不用再存储+排序。

时间复杂度:\(O(q+n^3)\)

const int N=210;
int g[N][N];
int tim[N];
int n,m,q;

void floyd(int k)
{
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}

int main()
{
    cin>>n>>m;

    for(int i=0;i<n;i++) cin>>tim[i];

    memset(g,0x3f,sizeof g);
    for(int i=0;i<n;i++) g[i][i]=0;

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

    cin>>q;
    int k=0;
    while(q--)
    {
        int x,y,t;
        cin>>x>>y>>t;

        while(k<n && tim[k] <= t)
        {
            floyd(k);
            k++;
        }

        if(g[x][y] == INF || tim[x] > t || tim[y] > t) puts("-1");
        else cout<<g[x][y]<<endl;
    }

    //system("pause");
}
posted @ 2020-09-05 12:55  Dazzling!  阅读(175)  评论(0编辑  收藏  举报