题目描述
在电视时代,没有多少人观看戏剧表演。Malidinesia古董喜剧演员意识到这一事实,他们想宣传剧院,尤其是古色古香的喜剧片。他们已经打印请帖和所有必要的信息和计划。许多学生被雇来分发这些请柬。每个学生志愿者被指定一个确切的公共汽车站,他或她将留在那里一整天,邀请人们参与。
这里的公交系统是非常特殊的:所有的线路都是单向的,连接两个站点。公共汽车离开起始点,到达目的地之后又空车返回起始点。学生每天早上从总部出发,乘公交车到一个预定的站点邀请乘客。每个站点都被安排了一名学生。在一天结束的时候,所有的学生都回到总部。现在需要知道的是,学生所需的公交费用的总和最小是多少。
输入输出格式
输入格式:第1行有两个整数n、m(1<=n,m<=1000000),n是站点的个数,m是线路的个数。
然后有m行,每行描述一个线路,包括3个整数,起始点,目的地和价格。
总部在第1个站点,价钱都是整数,且小于1000000000。
输出格式:输出一行,表示最小费用。
输入输出样例
输入样例#1
4 6 1 2 10 2 1 60 1 3 20 3 4 10 2 4 5 4 1 50
输出样例#1:
210
题解
此题比较水,就当学习一个技巧吧,如果要求所有点到一个点的距离,可以将所有边反向,然后从这个点求一下最短路。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #define inf 1000000000 #define ll long long using namespace std; queue<int>q; const int maxn=1000010; int pre[maxn],last[maxn],other[maxn],w[maxn],num; int pre1[maxn],last1[maxn],other1[maxn],w1[maxn],num1,n,m;; ll dis[maxn],ans; bool vis[maxn]; inline void add(int x,int y,int z){ num++; pre[num]=last[x]; last[x]=num; other[num]=y; w[num]=z; } inline void add1(int x,int y,int z){ num1++; pre1[num]=last1[x]; last1[x]=num; other1[num]=y; w1[num]=z; } inline void spfa(int *pre,int *last,int *other,int *w){ for(int i=1;i<=n;i++) dis[i]=inf; memset(vis,0,sizeof(vis)); q.push(1); dis[1]=0; vis[1]=1; while(!q.empty()){ int t=q.front(); vis[t]=0; q.pop(); for(int i=last[t];i;i=pre[i]){ int v=other[i]; if(dis[v]>dis[t]+w[i]){ dis[v]=dis[t]+w[i]; if(!vis[v]){ q.push(v); vis[v]=1; } } } } } int main(){ int x,y,z; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); add(x,y,z); add1(y,x,z); } ans=0; spfa(pre,last,other,w); for(int i=2;i<=n;i++) ans+=dis[i]; spfa(pre1,last1,other1,w1); for(int i=2;i<=n;i++) ans+=dis[i]; printf("%lld\n",ans); return 0; }