洛谷P1629 郵遞員送信(dijkstra算法+反向建圖)

在這裏插入圖片描述原題鏈接
思路:
答案包含兩部分
1.從1到其它所有點i的最短距離的和。
2.從其它所有點i到1的最短距離的和。
注意是單向邊。
第一反應是用floyed算法但是1e3的數據量明顯超時,最後我試了一下只有四十分。
看了別人的題解知道了還有建反向圖這種操作,我在這詳細說明一下。建反向圖其實就是:
比如d[i][j]代表從i到j的距離,反向的話就是把d[i][j]和d[j][i]互換過來。
原理是這樣的:
從u到v距離是w,那麼從v到u距離也是w,單純把方向反過來。說的話感覺總是說不到那個點子上,實在不行就畫個圖瞅瞅。
然後跑兩遍dijkstra就行了。
代碼:

#include<iostream>
#include<cmath>
#include<vector>
#include<string>
#include<fstream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int N=1e3+10,M=1e5+10;
struct edge
{
    int to,next,w;
};
struct node
{
    int to,w;
    node(int u=0,int ww=0):to(u),w(ww){}//構造函數
    bool operator<(const node&a)const
    {
        return w>a.w;
    }
};
edge e1[M],e2[M];
int head1[N],head2[N],cnt=0,n,m;
int dis_1[N],dis_2[N];
bool done_1[N],done_2[N];
void addedge(int u,int v,int w)
{
    e1[++cnt].to=v;
    e1[cnt].w=w;
    e1[cnt].next=head1[u];
    head1[u]=cnt;
    e2[cnt].to=u;
    e2[cnt].next=head2[v];
    e2[cnt].w=w;
    head2[v]=cnt;
}
void dijkstra_1()//正向圖
{
    for(int i=1;i<=n;i++) dis_1[i]=inf,done_1[i]=false;
    dis_1[1]=0;
    priority_queue<node>q;
    q.push(node(1,0));
    while(!q.empty())
    {
        node s=q.top();
        q.pop();
        if(done_1[s.to]) continue;
        done_1[s.to]=1;
        for(int i=head1[s.to];i;i=e1[i].next)
        {
            if(dis_1[s.to]+e1[i].w<dis_1[e1[i].to])
            {
                dis_1[e1[i].to]=dis_1[s.to]+e1[i].w;
                q.push(node(e1[i].to,dis_1[e1[i].to]));
            }
        }
    }
}
void dijkstra_2()//反向圖
{
    for(int i=1;i<=n;i++) dis_2[i]=inf,done_2[i]=false;
    dis_2[1]=0;
    priority_queue<node>q;
    q.push(node(1,0));
    while(!q.empty())
    {
        node s=q.top();
        q.pop();
        if(done_2[s.to]) continue;
        done_2[s.to]=1;
        for(int i=head2[s.to];i;i=e2[i].next)
        {
            if(dis_2[s.to]+e2[i].w<dis_2[e2[i].to])
            {
                dis_2[e2[i].to]=dis_2[s.to]+e2[i].w;
                q.push(node(e2[i].to,dis_2[e2[i].to]));
            }
        }
    }
}
int main()
{
    int u,v,w;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&u,&v,&w);
        addedge(u,v,w);
    }
    int ans=0;
    dijkstra_1();
    dijkstra_2();
    for(int i=2;i<=n;i++) ans+=dis_1[i]+dis_2[i];
    printf("%d\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章