邀请卡(正向和反向建图,跑dij)

邀请卡 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);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值