[JSOI2015]地铁线路

[JSOI2015]地铁线路

https://ac.nowcoder.com/acm/problem/20214

题意:
有n个站点,m条路线,每条路线使用一次要交1块钱,给出每条路线的信息,从一个站点到下一个站点的时间为1,让你求从一个站点到另一个站点的最小花费是多少,此时花费时间最大为多少?

思路:
最短路+拓扑+dp
一看就是图论题,第一问求最小花费,如何用最短路求呢,对于每一条路线我们要创建两个虚点,一个虚点记录从起点到终点,另一个记录从终点到起点,从起点到终点使虚点对该路线的每一个节点连一条花费为0,时间为从该节点到起点的距离,每一个点连接一条到虚点的边,花费为1,时间为从该节点到起点的距离的相反数,从终点到起点使虚点对该路线的每一个节点连一条花费为0,时间为从该节点到终点的距离,每一个点连接一条到虚点的边,花费为1,时间为从该节点到终点的距离的相反数.这样图就建好了,然后开始跑最短路,获取只包含最短路的最短路图,这图一定是有向无环图,然后边拓扑边dp求出最大花费时间为多少。

代码:

#include<bits/stdc++.h>

#define ll long long
#define eps 1e-8

using namespace std;

const ll inf=1e9+7;

struct w
{
    int to, dis, cost;
}w;

map<string,int> ma;
string s;
int qi, zh, d[1000005];

vector<struct w> g[1000005], g1[1000005];

struct p
{
    int v, cost;
}p, p2;

bool operator<(struct p a,struct p b)
{
    return a.cost>b.cost;
}

int in[1000005];

void djk()
{
    fill(d,d+1000005,inf);
    d[qi]=0;
    p.v=qi;
    p.cost=0;
    priority_queue<struct p> q;
    q.push(p);
    while(!q.empty())
    {
        p=q.top();
        q.pop();
        int v=p.v, t=p.cost;
        if(t>d[v])
        {
            continue;
        }
        for(int i=0;i<g[v].size();i++)
        {
            int u=g[v][i].to, cost=g[v][i].cost;
            if(d[u]>cost+t)
            {
                d[u]=t+cost;
                p2.cost=d[u];
                p2.v=u;
                q.push(p2);
            }
        }
    }
}

queue<int> q;
int dp[1000005];

void kp()
{
    fill(dp,dp+1000005,-inf);
    dp[qi]=0;
    while(!q.empty())
    {
        int v=q.front();
        q.pop();
        for(int i=0;i<g1[v].size();i++)
        {
            int u=g1[v][i].to;
            in[u]--;
            dp[u]=max(dp[u],dp[v]+g1[v][i].dis);
            if(in[u]==0)
            {
                q.push(u);
            }
        }
    }
}

int main()
{
    int n, m;
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++)
    {
        cin >> s;
        ma[s]=i;
    }
    for(int i=1;i<=m;i++)
    {
        int ki;
        scanf("%d",&ki);
        for(int j=1;j<=ki;j++)
        {
            cin >> s;
            int v=ma[s];
            w.to=v;
            w.dis=j-1;
            w.cost=1;
            g[n+i].push_back(w);
            w.to=n+i;
            w.dis=-(j-1);
            w.cost=0;
            g[v].push_back(w);
            w.to=v;
            w.dis=ki-j;
            w.cost=1;
            g[n+m+i].push_back(w);
            w.to=n+i+m;
            w.dis=-(ki-j);
            w.cost=0;
            g[v].push_back(w);
        }
    }
    cin >> s;
    qi=ma[s];
    cin >> s;
    zh=ma[s];
    djk();
    if(d[zh]==inf)
    {
        printf("-1\n0\n");
        return 0;
    }
    cout << d[zh] << endl;
    for(int i=1;i<=n+2*m;i++)
    {
        for(int j=0;j<g[i].size();j++)
        {
            int u=g[i][j].to;
            if(d[u]-d[i]==g[i][j].cost)
            {
                g1[i].push_back(g[i][j]);
                in[u]++;
            }
        }
    }
    for(int i=1;i<=n+2*m;i++)
    {
        if(in[i]==0)
        {
            q.push(i);
        }
    }
    kp();
    cout << dp[zh] << endl;
    return 0;
}
每日一题题解 文章被收录于专栏

写题解

全部评论

相关推荐

勤劳的香菇求被捞求offer:满帮笔试都不给我发 似乎被卡本了
投递满帮集团等公司10个岗位
点赞 评论 收藏
分享
10-09 09:39
门头沟学院 C++
HHHHaos:这也太虚了,工资就一半是真的
点赞 评论 收藏
分享
2 收藏 评论
分享
牛客网
牛客企业服务