logn me problem 1025(dij 反向建边)

已经没什么好害怕了
Case Time Limit: 2000 MS (Others) / 4000 MS (Java) Case Memory Limit: 256 MB (Others) / 512 MB (Java)
Accepted: 83 Total Submission: 408

查看我的提交显示标签
Problem Description

今天麻美学姐跟踪一些被魔女控制了心神的人类来到了魔女设下的结界前,这次要对付的魔女叫做分身魔女。分身魔女设下的结界内部共有N个空间,空间之间通过M条通道相连接。受到邪恶能量的影响,这些通道只能沿着指定的方向通过,且消耗麻美学姐体力的程度比平时更多。魔女平时化为K个分身,处于K个不同的空间中,只有将它们全部消灭,本体才会出现。麻美学姐可以随意进出魔女结界。

麻美学姐计划先消灭K个分身,然后消灭本体。研究结界之后发现,在结界中的许多空间并不能在进入结界时直接到达,而必须通过其他空间才能到达,但有P个空间可以在进入结界时直接到达,所有空间中只有这P个空间与外界连通,如果要离开结界也必须通过这P个空间。麻美学姐可以将这P个空间的任意一个作为出发点,然后沿着通道到达K个分身之一所在的空间(为了少消耗体力,麻美学姐总是选择消耗总体力最少的路径;在经过有分身的空间时也可以不消灭这个分身而前往其他空间)。用大招Tiro Finale消灭这个分身后,将沿着通道回到P个初始空间中的任意一个(同样也选择消耗总体力最少的路径),恢复体力后再去消灭下一个分身。而在最后一个分身被消灭后,魔女本体将直接出现在最后一个分身的空间,学姐将用她娴熟的战斗技巧打败她,并且自信满满地说:“已经没什么好害怕了”。魔女被消灭后,整个结界就会消失。
Input

每个输入文件一组数据。
对每组数据,第一行为四个整数N、M、P、K(0 < N <= 1000000, 0 <= M <= 1000000, 0 < P <= N, 0 < K <= N)。假设N个空间的编号为1到N。
接下来一行,包括P个正整数,表示P个初始空间的编号。
接下来一行,包括K个正整数,表示K个分身所在的空间编号。
接下来M行,每行三个正整数u、v、w(0 < u <= N, 0 < v <= N, u != v, 0 < w <= 10000000),表示一条从u号空间到达v号空间的通道,通过该通道需要消耗的体力值为w。
Output

输出一个整数,表示麻美学姐需要消耗的总体力值(就是把所有的消耗加起来)。数据保证所有分身都能被消灭。
Sample Input

4 6 2 2
1 2
3 4
1 3 1
3 1 1
2 4 3
4 2 5
1 4 4
3 4 1
Sample Output

4
Author

Shoutmon
Source

18浙大考研机试模拟赛

题意:(1)找源点到目标节点的最短距离,dij求出
(2)找目标节点到源点的最短距离,为了避免跑k次最短路,反向建边跑dij,源点到目标的最短距离即目标到源点的最短距离
注意:目标节点可能到不了源点

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N= 1e6+1000;
const  LL inf = 0x3fffffffffffffff;
int head1[N], head2[N], cnt1, cnt2;
void init()
{
    memset(head1,-1,sizeof(head1));
    memset(head2,-1,sizeof(head2));
    cnt1=0, cnt2=0;
    return ;
}
typedef long long LL;
struct node
{
    int u,v,next;
    LL w;
}p1[N],p2[N];

void add(int u,int v, LL w)
{
    p1[cnt1].u=u,p1[cnt1].v=v,p1[cnt1].w=w,p1[cnt1].next=head1[u],head1[u]=cnt1++;
    p2[cnt2].u=v,p2[cnt2].v=u,p2[cnt2].w=w,p2[cnt2].next=head2[v],head2[v]=cnt2++;
}
int a[N], b[N], vis[N];
LL dist1[N], dist2[N];
typedef pair<LL,int>pi;
void dij(int hx[],node px[],LL dx[])
{
    fill(dx,dx+N,inf);
    memset(vis,0,sizeof(vis));
    dx[0]=0;
    priority_queue<pi,vector<pi>,greater<pi>>q;
    q.push(make_pair(0,0));
    while(!q.empty())
    {
        int u=q.top().second;
        q.pop();
        for(int i=hx[u];i!=-1;i=px[i].next)
        {
            int v=px[i].v;
            if(dx[v]==inf||dx[v]>dx[u]+px[i].w)
            {
                dx[v]=dx[u]+px[i].w;
                if(!vis[v])
                {
                    vis[v]=1;
                    q.push(make_pair(dx[v],v));
                }
            }
        }
        vis[u]=0;
    }
    return ;
}
int main()
{
    init();
    int n, m, P, K;
    scanf("%d %d %d %d", &n, &m, &P, &K);
    for(int i=0;i<P;i++)
    {
        scanf("%d", &a[i]);
        add(0,a[i],0);
        add(a[i],0,0);
    }
    for(int i=0;i<K;i++)scanf("%d", &b[i]);
    for(int i=0;i<m;i++)
    {
        int x, y;
        LL z;
        scanf("%d %d %lld", &x, &y, &z);
        add(x,y,z);
    }
    dij(head1,p1,dist1);
    dij(head2,p2,dist2);
    LL ans=0, h=0;
    for(int i=0;i<K;i++)
    {
        ans=ans+dist1[b[i]]+dist2[b[i]];
        h=h>dist2[b[i]]?h:dist2[b[i]];
    }
    printf("%lld\n",ans-h);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值