<题目链接>

题目大意:

有向图,求从起点1到每个点的最短路然后再回到起点1的最短路之和。

解题分析:

在求每个点到1点的最短路径时,如果仅仅只是遍历每个点,对它们每一个都进行一次最短路算法,那么即使是用了堆优化的dijkstra,时间复杂度也高达$O(n^2log(n))$,而本题有1000000个点,毫无疑问,这种想法必然是不可行的,所以我们可以采用逆向思维,将图中的每一条有向边全部反向,然后以1为起点,仅做一次dijkstra,就能得到1到所有点的最短距离,即反向前的,所有点到1点的最短距离。所以,本题的正解应为:先以1为起点,做一次dijkstra,算出,1到所有点的最短距离,然后将边反向,再以1为起点,做一次dijkstra,此时就能得到,其他所有点到1的最短距离,将所有的最短距离相加,即为答案。时间复杂度为$O(nlogn)$。

 #include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std; #define INF 0x3f3f3f3f
const int maxn =+; int n,m;
struct Edge{
int to;
int next;
int w;
}; Edge edge[maxn],redge[maxn]; struct NODE{
int index;
int dis;
bool operator < (NODE const &tmp)const{
return dis>tmp.dis;
}
}d[maxn]; int dist[maxn];
int cnt,rcnt,head1[maxn],head2[maxn],vis[maxn]; void init(){
memset(head1,-,sizeof(head1));
memset(head2,-,sizeof(head2));
cnt=,rcnt=;
} void add1(int u,int v,int w){
edge[cnt].to=v;edge[cnt].w=w;
edge[cnt].next=head1[u];
head1[u]=cnt++;
} void add2(int u,int v,int w){
redge[rcnt].to=v;redge[rcnt].w=w;
redge[rcnt].next=head2[u];
head2[u]=rcnt++;
} void dijkstra1(int st){
for(int i=;i<=n;i++){
vis[i]=;d[i].dis=INF,d[i].index=i;
} priority_queue<NODE>q;
d[st].dis=;q.push(d[st]);
while(!q.empty()){
int u=q.top().index;
q.pop();
if(vis[u])continue;
vis[u]=;
for(int i=head1[u];i!=-;i=edge[i].next){
int v=edge[i].to;
if(d[v].dis>d[u].dis+edge[i].w){
d[v].dis=d[u].dis+edge[i].w;
q.push(d[v]);
}
}
}
} void dijkstra2(int st){ //因为正、反向边的edge[],和head[]散组不同,所以要将另外再写一个dijkstra函数
for(int i=;i<=n;i++){
vis[i]=;d[i].dis=INF,d[i].index=i;
} priority_queue<NODE>q;
d[st].dis=;q.push(d[st]);
while(!q.empty()){
int u=q.top().index;
q.pop();
if(vis[u])continue;
vis[u]=;
for(int i=head2[u];i!=-;i=redge[i].next){
int v=redge[i].to;
if(d[v].dis>d[u].dis+redge[i].w){
d[v].dis=d[u].dis+redge[i].w;
q.push(d[v]);
}
}
}
} int main(){
int t;scanf("%d",&t);
while(t--){
scanf("%d %d",&n,&m);
init();
for(int i=;i<=m;i++){
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
add1(a,b,c); //存储该有向图正确的边
add2(b,a,c); //将该有向图的所有边反向存储
} long long sum=; dijkstra1(); //边未反向之前,求出1到所有点的最短路
for(int i=;i<=n;i++){
sum+=d[i].dis;
} dijkstra2(); //将边反向后,求出所有点到1点的最短路
for(int i=;i<=n;i++){
sum+=d[i].dis;
}
printf("%lld\n",sum);
}
return ;
}

2018-08-27

POJ-1511 Invitation Cards (单源最短路+逆向)的更多相关文章

  1. Invitation Cards POJ - 1511 (双向单源最短路)

    In the age of television, not many people attend theater performances. Antique Comedians of Malidine ...

  2. POJ 1511 Invitation Cards / UVA 721 Invitation Cards / SPOJ Invitation / UVAlive Invitation Cards / SCU 1132 Invitation Cards / ZOJ 2008 Invitation Cards / HDU 1535 (图论,最短路径)

    POJ 1511 Invitation Cards / UVA 721 Invitation Cards / SPOJ Invitation / UVAlive Invitation Cards / ...

  3. poj 1511 Invitation Cards (最短路)

    Invitation Cards Time Limit: 8000MS   Memory Limit: 262144K Total Submissions: 33435   Accepted: 111 ...

  4. POJ 1511 Invitation Cards(单源最短路,优先队列优化的Dijkstra)

    Invitation Cards Time Limit: 8000MS   Memory Limit: 262144K Total Submissions: 16178   Accepted: 526 ...

  5. poj 1511 Invitation Cards(最短路中等题)

    In the age of television, not many people attend theater performances. Antique Comedians of Malidine ...

  6. POJ 1511 Invitation Cards (最短路spfa)

    Invitation Cards 题目链接: http://acm.hust.edu.cn/vjudge/contest/122685#problem/J Description In the age ...

  7. [POJ] 1511 Invitation Cards

    Invitation Cards Time Limit: 8000MS   Memory Limit: 262144K Total Submissions: 18198   Accepted: 596 ...

  8. DIjkstra(反向边) POJ 3268 Silver Cow Party || POJ 1511 Invitation Cards

    题目传送门 1 2 题意:有向图,所有点先走到x点,在从x点返回,问其中最大的某点最短路程 分析:对图正反都跑一次最短路,开两个数组记录x到其余点的距离,这样就能求出来的最短路以及回去的最短路. PO ...

  9. POJ 1511 Invitation Cards (spfa的邻接表)

    Invitation Cards Time Limit : 16000/8000ms (Java/Other)   Memory Limit : 524288/262144K (Java/Other) ...

  10. Poj 1511 Invitation Cards(spfa)

    Invitation Cards Time Limit: 8000MS Memory Limit: 262144K Total Submissions: 24460 Accepted: 8091 De ...

随机推荐

  1. JavaScript之12306自动刷新车票[待完善]

    function refresh(){ var search_btn = document.getElementById("query_ticket"); var result_t ...

  2. 微信小程序开发工具的基本应用

    全局配置: 1.1配置所有页面路径:在app.json的{pages:[配置所有页面]},将首页放置在第一位,在app.json必须写上所有页面的路径,要不然会报错,每个页面的wxss样式文件只在当前 ...

  3. 【文件】使用word的xml模板生成.doc文件

    一.编辑模板 替换地方以变量标记如“案件编号”可写成{caseNo} template.xml 二.准备数据 以HashMap封装数据,原理是替换模板中的变量 三.替换操作 选择输出位置:writeP ...

  4. I - Older Brother Gym - 101490I

    题目链接:https://cn.vjudge.net/problem/Gym-101490I 题目大意:给你一个整数,问你这个整数能不能表示成一个素数的k次方? 具体思路:对于每一个数,我们先判断他是 ...

  5. MGR架构 ~ MGR+proxysql(2)

    一 简介: 上篇环境已经搭建完成,我们开始进行测试 二 工具和环境: sysbench ,mgr+proxysql 三 测试方式: sysbench+oltp.lua脚本 四 模拟故障 1 并发环境观 ...

  6. 【Udacity并行计算课程笔记】- Lesson 3 Fundamental GPU Algorithms (Reduce, Scan, Histogram)

    本周主要内容如下: 如何分析GPU算法的速度和效率 ​​3个新的基本算法:归约.扫描和直方图(Reduce.Scan.Histogram) 一.评估标准 首先介绍用于评估GPU计算的两个标准: ste ...

  7. Docker三要素

    一.镜像(Image) Docker镜像(Image)就是一个只读的模板,镜像可以用来创建Docker容器,一个镜像可以创建很多容器. Docker 面向对象 镜像 类(class) 容器 实例对象 ...

  8. ubuntu16.04安装opencv2.4.13

    1.更新 sudo apt-get update sudo apt-get upgrade 2.安装关联库 2.1 搭建C/C++编译环境 sudo apt-get install build-ess ...

  9. ftruncate(改变文件大小)

    ftruncate(改变文件大小) 定义函数 int ftruncate(int fd,off_t length); 函数说明 ftruncate()会将参数fd指定的文件大小改为参数length指定 ...

  10. java并发编程系列二:原子操作/CAS

    什么是原子操作 不可被中断的一个或者一系列操作 实现原子操作的方式 Java可以通过锁和循环CAS的方式实现原子操作 CAS( Compare And Swap )  为什么要有CAS? Compar ...