p1342 请柬
P1342
最短路的反向建图(请柬)
题目背景
在电视时代,没有多少人观看戏剧表演。 Malidinesia 古董喜剧演员意识到这一事实,他们想宣传剧院,尤其是古色古香的喜剧片。
题目描述
他们已经打印了请帖和所有必要的信息和计划。许多学生被雇来分发这些请柬。每个学生志愿者被指定一个确切的公共汽车站,他或她将留在那里一整天,邀请人们参与。
这里的公交系统是非常特殊的:共有 n n n 个站点和 m m m 个线路,所有的线路都是单向的,连接两个站点。公共汽车离开起始点,到达目的地之后又空车返回起始点。
学生每天早上从总部所在的 1 1 1 号站点出发,乘公交车到一个预定的站点邀请乘客。每个站点都被安排了一名学生。在一天结束的时候,所有的学生都回到总部。现在需要知道的是,学生所需的公交费用的总和最小是多少。
输入格式
输入的第一行是两个整数,代表站点个数 n n n 和线路条数 m m m。
第 2 2 2 到第 ( m + 1 ) (m + 1) (m+1) 行,每行三个整数 u , v , w u, v, w u,v,w,代表存在一条从 u u u 出发到达 v v v 的线路,费用为 w w w。
输出格式
输出一行一个整数,表示最小费用。
样例 #1
样例输入 #1
4 6
1 2 10
2 1 60
1 3 20
3 4 10
2 4 5
4 1 50
样例输出 #1
210
提示
数据规模与约定
对于 100 % 100\% 100% 的数据,保证:
- 1 ≤ n , m ≤ 1 0 6 1 \leq n, m \leq 10^6 1≤n,m≤106。
- 1 ≤ u , v ≤ n 1 \leq u, v \leq n 1≤u,v≤n, 1 ≤ w ≤ 1 0 9 1 \leq w \leq 10^9 1≤w≤109。
- 从 1 1 1 出发可以到达所有的站点。
思路:反向建图,head1是一个正向的从1到其他点,head2是其他点到1的
#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <queue>
#define ll long long
using namespace std;
const int maxn=1e6+10;
const ll inf=1e18;
ll dis[maxn];
bool vis[maxn];
int n,m,head1[maxn<<2],head2[maxn<<2],cnt1,cnt2;
struct edge
{
int next,to,w;
}e1[maxn<<2],e2[maxn<<2];
struct node
{
int pos,dis;
friend bool operator <(const node x,const node y)
{
return x.dis>y.dis;
}
};
priority_queue<node>q;
void add (int f,int u,int v,int w)
{
if (f==1)
{
e1[++cnt1].next=head1[u];
e1[cnt1].to=v;
e1[cnt1].w=w;
head1[u]=cnt1;
return ;
}
else if (f==2)
{
e2[++cnt2].next=head2[u];
e2[cnt2].to=v;
e2[cnt2].w=w;
head2[u]=cnt2;
return ;
}
}
void dijkstra (int *head,edge *e,int s)
{
for (int i=1;i<=n;i++)
{
dis[i]=inf;
vis[i]=false;
}
node st,be,en;
st.pos=s;
st.dis=0;
dis[s]=0;
q.push(st);
while (!q.empty())
{
be=q.top();
q.pop();
int u=be.pos;
if (vis[u]) continue ;
vis[u]=true;
for (int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
if (dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
en.dis=dis[v];
en.pos=v;
q.push(en);
}
}
}
return ;
}
int main ()
{
scanf ("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int u,v,w;
scanf ("%d%d%d",&u,&v,&w);
add(1,u,v,w);
add(2,v,u,w);
}
dijkstra(head1,e1,1);
ll ans=0;
for (int i=1;i<=n;i++)
{
ans+=dis[i];
}
dijkstra(head2,e2,1);
for (int i=1;i<=n;i++)
{
ans+=dis[i];
}
printf ("%lld\n",ans);
system("pause");
return 0;
}