Invitation Cards

Description
In the age of television, not many people attend theater performances. Antique Comedians of Malidinesia are aware of this fact. They want to propagate theater and, most of all, Antique Comedies. They have printed invitation cards with all the necessary information and with the programme. A lot of students were hired to distribute these invitations among the people. Each student volunteer has assigned exactly one bus stop and he or she stays there the whole day and gives invitation to people travelling by bus. A special course was taken where students learned how to influence people and what is the difference between influencing and robbery.
The transport system is very special: all lines are unidirectional and connect exactly two stops. Buses leave the originating stop with passangers each half an hour. After reaching the destination stop they return empty to the originating stop, where they wait until the next full half an hour, e.g. X:00 or X:30, where 'X' denotes the hour. The fee for transport between two stops is given by special tables and is payable on the spot. The lines are planned in such a way, that each round trip (i.e. a journey starting and finishing at the same stop) passes through a Central Checkpoint Stop (CCS) where each passenger has to pass a thorough check including body scan.
All the ACM student members leave the CCS each morning. Each volunteer is to move to one predetermined stop to invite passengers. There are as many volunteers as stops. At the end of the day, all students travel back to CCS. You are to write a computer program that helps ACM to minimize the amount of money to pay every day for the transport of their employees.
Input
The input consists of N cases. The first line of the input contains only positive integer N. Then follow the cases. Each case begins with a line containing exactly two integers P and Q, 1 <= P,Q <= 1000000. P is the number of stops including CCS and Q the number of bus lines. Then there are Q lines, each describing one bus line. Each of the lines contains exactly three numbers - the originating stop, the destination stop and the price. The CCS is designated by number 1. Prices are positive integers the sum of which is smaller than 1000000000. You can also assume it is always possible to get from any stop to any other stop.
Output
For each case, print one line containing the minimum amount of money to be paid each day by ACM for the travel costs of its volunteers.
Sample Input
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
Sample Output
46
210

题目大意:
    有编号1~P的站点, 有Q条公交车路线,公交车路线只从一个起点站直接到达终点站,是单向的,每条路线有它自己的车费。

    有P个人早上从1出发,他们要到达每一个公交站点, 然后到了晚上再返回点1。 求所有人来回的最小费用之和。

解题思路:

    求两边最短路,第二遍把边反向。求总和就行了。

    PS:这个题数据比较多和大,使用dijkstra算法和SPFA算法会超时,需要优化。具体细节看备注。

Code1(dijkstra算法+邻接表):

 #include<cstdio>
#include<cstring>
#include<climits>
#include<algorithm>
#define N 1000000
using namespace std;
int a[N+],b[N+],c[N+],n,m,k;
int dis[N+],vis[N+],first[N+],next[N+];
void dijkstra(int pos,int *a,int *b,int *c)
{
int i,j,min;
for(i=;i<=n;i++)
dis[i]=INT_MAX;
memset(vis,,sizeof(vis));
vis[pos]=;
i=first[pos];
while(i!=-){
dis[b[i]]=c[i];
i=next[i];
}
dis[pos]=;
for(i=;i<n;i++){
min=INT_MAX;
for(j=;j<=n;j++)
if(!vis[j]&&dis[j]<min){
min=dis[j];
pos=j;
}
vis[pos]=;
j=first[pos];
while(j!=-){
if(!vis[b[j]]&&dis[pos]+c[j]<dis[b[j]])
dis[b[j]]=dis[pos]+c[j];
j=next[j];
}
}
}
void jiantu(int *a,int *b,int *c)
{
int i;
memset(first,-,sizeof(first));
for(i=;i<=m;i++){
next[i]=first[a[i]];
first[a[i]]=i;
}
}
int main()
{
int T,i,sum;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(i=;i<=m;i++)
scanf("%d%d%d",&a[i],&b[i],&c[i]);
jiantu(a,b,c);
dijkstra(,a,b,c);
sum=;
for(i=;i<=n;i++)
sum+=dis[i];
jiantu(b,a,c);
dijkstra(,b,a,c);
for(i=;i<=n;i++)
sum+=dis[i];
printf("%d\n",sum);
}
return ;
}

Code2(SPFA+优化):

 #include<stdio.h>
#include<limits.h>
#include<iostream>
#include<string>
#include<queue>
#define MAXN 1000000
using namespace std;
struct e
{
int begin;
int end;
int dis;
} edge1[MAXN+],edge2[MAXN+];
int dis[MAXN+],first[MAXN+];
bool vis[MAXN+];
int T,S,D,N,k,M;
void SPFA(int begin,struct e edge[])
{
for (int i=; i<=N; i++)
{
dis[i]=INT_MAX;
vis[i]=;
}
queue <int> Q;
Q.push(begin);
dis[begin]=;
while (!Q.empty())
{
begin=Q.front();
Q.pop();
vis[begin]=;
for (int i=first[begin]; edge[i].begin==begin; i++) //可以只遍历begin==edge[i].begin的edge
if (dis[edge[i].end]>dis[begin]+edge[i].dis)
{
dis[edge[i].end]=dis[begin]+edge[i].dis;
if (!vis[edge[i].end])
{
Q.push(edge[i].end);
vis[edge[i].end]=;
}
}
}
}
void init(struct e edge[]) //first存各个顶点作为结点时的第一个下标
{
memset(first,,sizeof(first));
first[edge[].begin]=;
for (int i=;i<=M;i++)
if (edge[i-].begin!=edge[i].begin) first[edge[i].begin]=i;
}
bool cmp(struct e a,struct e b)
{
return a.begin<b.begin;
}
int main()
{
int T;
cin>>T;
while (T--)
{
scanf("%d %d",&N,&M);
int x1,x2,x3;
for (int i=; i<=M; i++)
{
scanf("%d %d %d",&x1,&x2,&x3); //cin跑了2600ms scanf只要1300ms
//cin>>x1>>x2>>x3;
edge1[i].begin=x1,edge1[i].end=x2,edge1[i].dis=x3;
edge2[i].begin=x2,edge2[i].end=x1,edge2[i].dis=x3;
}
sort(edge1+,edge1+M+,cmp); //按begin顶点排序
sort(edge2+,edge2+M+,cmp);
init(edge1);
SPFA(,edge1);
int cnt=;
for (int i=; i<=N; i++)
cnt+=dis[i];
init(edge2);
SPFA(,edge2);
for (int i=; i<=N; i++)
cnt+=dis[i];
printf("%d\n",cnt);
}
return ;
}

HDU1535——Invitation Cards(最短路径:SPAF算法+dijkstra算法)的更多相关文章

  1. 最短路径算法-Dijkstra算法的应用之单词转换(词梯问题)(转)

    一,问题描述 在英文单词表中,有一些单词非常相似,它们可以通过只变换一个字符而得到另一个单词.比如:hive-->five:wine-->line:line-->nine:nine- ...

  2. 最短路径问题的Dijkstra算法

      问题 最短路径问题的Dijkstra算法 是由荷兰计算机科学家艾兹赫尔·戴克斯特拉提出.迪科斯彻算法使用了广度优先搜索解决非负权有向图的单源最短路径问题,算法终于得到一个最短路径树>    ...

  3. 单源最短路径问题2 (Dijkstra算法)

    用邻接矩阵 /* 单源最短路径问题2 (Dijkstra算法) 样例: 5 7 0 1 3 0 3 7 1 2 4 1 3 2 2 3 5 2 4 6 3 4 4 输出: [0, 3, 7, 5, 9 ...

  4. 图论(四)------非负权有向图的单源最短路径问题,Dijkstra算法

    Dijkstra算法解决了有向图G=(V,E)上带权的单源最短路径问题,但要求所有边的权值非负. Dijkstra算法是贪婪算法的一个很好的例子.设置一顶点集合S,从源点s到集合中的顶点的最终最短路径 ...

  5. 单源最短路径—Bellman-Ford和Dijkstra算法

    Bellman-Ford算法:通过对边进行松弛操作来渐近地降低从源结点s到每个结点v的最短路径的估计值v.d,直到该估计值与实际的最短路径权重相同时为止.该算法主要是基于下面的定理: 设G=(V,E) ...

  6. 《算法导论》读书笔记之图论算法—Dijkstra 算法求最短路径

    自从打ACM以来也算是用Dijkstra算法来求最短路径了好久,现在就写一篇博客来介绍一下这个算法吧 :) Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的 ...

  7. 最短路径算法——Dijkstra算法

    在路由选择算法中都要用到求最短路径算法.最出名的求最短路径算法有两个,即Bellman-Ford算法和Dijkstra算法.这两种算法的思路不同,但得出的结果是相同的. 下面只介绍Dijkstra算法 ...

  8. C++编程练习(11)----“图的最短路径问题“(Dijkstra算法、Floyd算法)

    1.Dijkstra算法 求一个顶点到其它所有顶点的最短路径,是一种按路径长度递增的次序产生最短路径的算法. 算法思想: 按路径长度递增次序产生算法: 把顶点集合V分成两组: (1)S:已求出的顶点的 ...

  9. 单源最短路径问题之dijkstra算法

    欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. 算法的原理 以源点开始,以源点相连的顶点作为向外延伸的顶点,在所有这些向外延伸的顶 ...

随机推荐

  1. python pil 安装

    Ubuntu下 sudo pip install pil 安装PIL可能会出现问题,例如安装完成时显示JPEG support not available 或者 ZLIB (PNG/ZIP) supp ...

  2. Android版的疯狂猜图游戏源码完整版分享

    这个游戏源码是在安装教程网那么分享过来的,Android版的疯狂猜图游戏源码完整版分享,也是本人之前很早以前发的一款游戏源码的,大家如果想了解一下,可以看看吧,不说多了,上一个图先吧.   > ...

  3. stl::search

    template<class ForwardIt1, class ForwardIt2> ForwardIt1 search(ForwardIt1 first, ForwardIt1 la ...

  4. WCF 初识(一)

    WCF的前世今生 在.NETFramework 2.0以及前版本中,微软发展了Web Service(SOAP with HTTP communication),.NET Remoting(TCP/H ...

  5. 第一章 基本的SQL语句 (SQL基础)

    1. 查询数据库系统时间,常以服务器默认的格式进行显示(根据数据库的字符集而定): 注意:dual 为数据库中的虚表,隶属于管理员 sys 用户,但所有的用户都可以访问:无实际意义,仅充当select ...

  6. HTMLParser获取属性名

    HTMLParser获取属性名方式: 原始网页文本: <a title="美军被曝虐尸" href="http://www.sogou.com/web?query= ...

  7. Contest2037 - CSU Monthly 2013 Oct (problem D :CX and girls)

    [题解]: 最短路径问题,保证距离最短的同时,学妹权值最大,哈哈 [code]: #include<iostream> #include<queue> #include< ...

  8. CSS两列及三列自适应布局方法整理

    布局 自适应 两列 三列 在传统方法的基础上加入了Flex布局并阐述各方法的优缺点,希望对大家有所帮助.先上目录: 两列布局:左侧定宽,右侧自适应 方法一:利用float和负外边距 方法二:利用外边距 ...

  9. 4.1 spring-alias 标签的解析;

    对于之前漫长的,最核心的Bean标签的解析就没什么好讲的了, 首先看看使用方法: <bean id="car" name="cat0" class=&qu ...

  10. (五)乱入之如何使用MNIST数据库

    (五)乱入之如何使用MNIST数据库 今天花了整整一天时间查各种资料,终于搞清楚了怎么使用MNIST数据库.哈哈,MNIST,是不是高端洋气上档次?是不是不知道是什么东东? MNIST是一个据说很出名 ...