邀请卡 POJ - 1511
在电视时代,参加戏剧表演的人并不多。Malidinesia 的古董喜剧演员都知道这一事实。他们想宣传戏剧,最重要的是宣传古董喜剧。他们打印了包含所有必要信息和节目的邀请卡。许多学生受雇来向人们分发这些请柬。每个学生志愿者都指定了一个公交车站,他或她整天呆在那里,并邀请乘坐公交车旅行的人。开设了一门特殊课程,学生们学习如何影响他人以及影响和抢劫之间的区别。
交通系统非常特别:所有线路都是单向的,正好连接两个站点。巴士每半小时与乘客一起离开始发站。到达目的地站后,他们空车返回始发站,在那里等待下一个完整的半小时,例如 X:00 或 X:30,其中“X”表示小时。两个站点之间的交通费用由专门的表格给出,并在现场支付。这些线路的规划方式是,每次往返(即在同一站点开始和结束的旅程)都经过中央检查站 (CCS),每位乘客都必须通过包括身体扫描在内的全面检查。
所有 ACM 学生成员每天早上离开 CCS。每个志愿者将移动到一个预定的站点来邀请乘客。志愿者的数量和站点一样多。在一天结束时,所有学生都返回 CCS。您将编写一个计算机程序,帮助 ACM 最大限度地减少员工每天支付的交通费用。
输入
输入由 N 个案例组成。输入的第一行只包含正整数 N。然后按照案例。每个案例都以包含两个整数 P 和 Q 的行开始,1 <= P,Q <= 1000000。P 是包含 CCS 的站点数量,Q 是公交线路的数量。然后有 Q 条线,每条线描述一条总线。每行正好包含三个数字 - 始发站、目的地站和价格。CCS 由数字 1 指定。价格是正整数,其总和小于 1000000000。您还可以假设始终可以从任何停靠点到达任何其他停靠点。
输出
对于每个案例,打印一行,其中包含 ACM 每天为其志愿者的旅行费用支付的最低金额。
样本输入
2
2 2
1 2 13
2 1 33
4 6
1 2 10
2 1 60
1 3 20
3 4 10
2 4 5
4 1 50
样本输出
46
210
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn=1000005;
const ll inf=0x3f3f3f3f3f3f3f3f;
int vist[maxn],cnt=0;
ll head1[maxn],head2[maxn];
ll dis1[maxn],dis2[maxn];
struct node{
ll dian;
ll zhi;
friend bool operator<(const node& a,const node& b){
return a.zhi>b.zhi;
}
};
template<typename T>
inline void read(T &x)
{
T s=0,f=1;
char ch;
ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
s=(s<<3)+(s<<1)+(ch^'0');
ch=getchar();
}
x=f*s;
}
struct Edge{
ll to;
ll w;
ll next;
}edge1[maxn],edge2[maxn];
void into()
{
//memset(dis1,inf,sizeof(dis1));
//memset(dis2,inf,sizeof(dis2));
fill(dis1,dis1+maxn,inf);//注意double 数组这样赋值比较好
fill(dis2,dis2+maxn,inf);
memset(head1,-1,sizeof(head1));
memset(head2,-1,sizeof(head2));
}
void add_edge(int u,int v,int w)
{
edge1[cnt].to=v;
edge1[cnt].w=w;
edge1[cnt].next=head1[u];
head1[u]=cnt;
edge2[cnt].to=u;
edge2[cnt].w=w;
edge2[cnt].next=head2[v];
head2[v]=cnt;
cnt++;
}
void dj1()
{
memset(vist,0,sizeof(vist));
dis1[1]=0;
priority_queue<node> q;
q.push({1,0});
while(!q.empty()){
node cur=q.top();
q.pop();
ll dang=cur.dian;
if(vist[dang]) continue;
vist[dang]=1;
for(int i=head1[dang];i!=-1;i=edge1[i].next){
ll next=edge1[i].to;
if(!vist[next]&&dis1[dang]+edge1[i].w<dis1[next]){//注意有前提是这个点没有被标记过才更新。
dis1[next]=dis1[dang]+edge1[i].w;
q.push({next,dis1[next]});
}
}
}
}
void dj2()
{
memset(vist,0,sizeof(vist));
dis2[1]=0;
priority_queue<node> q;
q.push({1,0});
while(!q.empty()){
node cur=q.top();
q.pop();
ll dang=cur.dian;
if(vist[dang]) continue;
vist[dang]=1;
for(int i=head2[dang];i!=-1;i=edge2[i].next){
ll next=edge2[i].to;
if(!vist[next]&&dis2[dang]+edge2[i].w<dis2[next]){
dis2[next]=dis2[dang]+edge2[i].w;
q.push({next,dis2[next]});
}
}
}
}
int main()
{
int t,i,j,n,m;
ll u,v,w;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
cnt=0;
into();
for(i=1;i<=m;i++){
read(u);
read(v);
read(w);
add_edge(u,v,w);
}
ll ans=0;
dj1();
dj2();
for(i=1;i<=n;i++){
ans=ans+dis1[i]+dis2[i];//出发和回来的费用加起来
}
printf("%lld\n",ans);
}
}