P1342 请柬 建反图+dijkstra

题目链接

一句话题意:喊你求出从1出发到所有点的最短路以及所有点的最短路到1的最短路之和。

从1开始跑最短路很容易,直接一遍堆优化dijkstra就完了。

对于其他点到1的最短路又怎么求,不可能一个一个的求,所以想到之前暑假讲关于图论的技巧——建反图。

这样的话问题就迎刃而解了,再在反图上从1开始跑一遍最短路就完了。

代码如下:

 

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e6+7;
const int inf=0x7fffffff;
struct node1{
    int nxt,to,val;
}edge1[maxn*3];
struct node2{
    int nxt,to,val;
}edge2[maxn*3];
priority_queue<pair<long long ,int > >q1;
priority_queue<pair<long long ,int > >q2;
long long dis1[maxn],dis2[maxn];
int cnt1,cnt2;
int n,m;
int x,y,v;
int head1[maxn],head2[maxn];
void add1(int x,int y,int v){
    edge1[++cnt1].nxt=head1[x];
    edge1[cnt1].to=y;
    edge1[cnt1].val=v;
    head1[x]=cnt1;
} 
void add2(int x,int y,int v){
    edge2[++cnt2].nxt=head2[x];
    edge2[cnt2].to=y;
    edge2[cnt2].val=v;
    head2[x]=cnt2;
}
bool vis1[maxn];
long long ans1;
void dijkstra1(int x){
    for(int i=1;i<=n;i++){
        dis1[i]=inf;
        vis1[i]=false;
    }
    dis1[x]=0;
    q1.push(make_pair(0,x));
    while(q1.size()){
        int u=q1.top().second;
        q1.pop();
        if(vis1[u]) continue;
        vis1[u]=true;
        for(int i=head1[u];i;i=edge1[i].nxt){
            int v=edge1[i].to;
            if(dis1[v]>dis1[u]+edge1[i].val){
                dis1[v]=dis1[u]+edge1[i].val;
                q1.push(make_pair(-dis1[v],v));
            }
        }
    }
    for(int i=1;i<=n;i++) ans1+=dis1[i];
}
long long ans2;
bool vis2[maxn];
void dijkstra2(int x){
    for(int i=1;i<=n;i++){
        vis2[i]=false;
        dis2[i]=inf;
    }
    dis2[x]=0;
    q2.push(make_pair(0,x));
    while(q2.size()!=0){
        int u=q2.top().second;
        q2.pop();
        if(vis2[u]) continue;
        for(int i=head2[u];i;i=edge2[i].nxt){
            int v=edge2[i].to;
            if(dis2[v]>dis2[u]+edge2[i].val){
                dis2[v]=dis2[u]+edge2[i].val;
                q2.push(make_pair(-dis2[v],v));
            }
        }
    }
    for(int i=1;i<=n;i++) ans2+=dis2[i];
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&v);
        add1(x,y,v);
        add2(y,x,v);
    }
    dijkstra1(1);
    dijkstra2(1);
    long long final=ans1+ans2;
    printf("%lld\n",final);
    return 0;
}
View Code

 

posted @ 2019-09-21 00:16  JBLee  阅读(162)  评论(0编辑  收藏  举报