题意:

给定一个有向图,求从源点到其他各点的往返最短路径和。且这个图有一个性质:任何一个环都会经过源点。

图中的节点个数范围:0~100w;

分析:

我们先可以利用Dijkstra算法求解从源点到其余各点的最短距离,这样工作就完成了一半了。

那么如何求解从各点到源点的最短路呢?

1. 我们可以循环n-1次,每次计算点i到其余各点的最短路,从中取出i到源点的最短路,这样我们就可以其余各点到源点的最短路。

显然上述方法中存在大量冗余,显然针对题目的取值范围:0~100w,必定会超时的。如果你不信,可以试试。

按照上诉方法实践,超时的代码:

#include<cstdio>
#include<string.h>
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define maxn 1000000
#define inf 0x3f3f3f3f
typedef pair<int,int> P;
struct edge{
int t;
int c;
edge(){ t=0,c=0;}
edge(int tt,int cc){
t=tt,c=cc;
}
};
int dist[maxn];
vector<edge> map[maxn];
void dijkstra(int s,int n){
priority_queue<P,vector<P>,greater<P> > Q;
for(int i=1;i<=n;i++)
dist[i]=inf;
dist[s]=0;
bool visited[maxn];
memset(visited ,0,sizeof(visited)); Q.push(P(0,s));
while(!Q.empty()){
int v=Q.top().second;
Q.pop();
if(visited[v]) continue;
visited[v]=true;
for(int i=0;i<map[v].size();i++){
edge e=map[v][i];
if(dist[e.t]>dist[v]+e.c){
dist[e.t]=dist[v]+e.c;
Q.push(P(dist[e.t],e.t));
}
}
}
}
void init(int n){
for(int i=0;i<=n;i++){
map[i].clear();
}
}
int main(){
//freopen("in.txt","r",stdin);
int cases;
scanf("%d",&cases);
for(int t=1;t<=cases;t++){
int n,m;
scanf("%d %d",&n,&m);
init(n);
while(m--){
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
map[a].push_back(edge(b,c));
}
dijkstra(1,n);
int sum=0;
for(int i=1;i<=n;i++)
sum+=dist[i];
for(int i=2;i<=n;i++){
dijkstra(i,n);
sum+=dist[1];
}
printf("%d\n",sum);
}
}

2.经过别人题解指点,发现一个很好的方法。

首先,我们需要构造原图的反图。

原图为有向图,反图为建立在原图的基础之上,原图的边的源点为反图的终点,原图的边的终点为反图的源点。

总之,把原图的边的方向全部反转,就构成了反图。

在构建完反图后,我们再来对反图应用Dijkstra算法,源点为1.

接着,我们获得了从源点到其余各点的最短距离,注意我们的图是原图的反图,所以:

我们获得的其实是其余各点到源点的最短距离。

3.邻接表还是二维矩阵?

我们还需注意一个重要的问题:如何存储边信息?

按照题目中的数据范围0-100w,我们是无法开辟那么大的二维矩阵的,所以我们必须利用邻接表存储。

在这里我们使用vector实现。

源代码:

#include<cstdio>
#include<string.h>
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define maxn 1000001
#define inf 0x3f3f3f3f
typedef pair<int,int> P;
struct edge{
int f;
int t;
int c;
edge(){ f=0,t=0,c=0;}
edge(int ff,int tt,int cc){
f=ff,t=tt,c=cc;
}
};
int dist[maxn];
vector<edge> map[maxn];
edge edges[maxn];
void dijkstra(int s,int n){
priority_queue<P,vector<P>,greater<P> > Q;
for(int i=1;i<=n;i++)
dist[i]=inf;
dist[s]=0;
bool visited[maxn];
memset(visited ,0,sizeof(visited)); Q.push(P(0,s));
while(!Q.empty()){
int v=Q.top().second;
Q.pop();
if(visited[v]) continue;
visited[v]=true;
for(int i=0;i<map[v].size();i++){
edge e=map[v][i];
if(dist[e.t]>dist[v]+e.c){
dist[e.t]=dist[v]+e.c;
Q.push(P(dist[e.t],e.t));
}
}
}
}
void init(int n){
for(int i=0;i<=n;i++){
map[i].clear();
}
}
int main(){
//freopen("in.txt","r",stdin);
int cases;
scanf("%d",&cases);
for(int t=1;t<=cases;t++){
int n,m;
scanf("%d %d",&n,&m);
init(n);
for(int i=1;i<=m;i++){
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
edges[i]=edge(a,b,c);
map[a].push_back(edge(a,b,c));
}
dijkstra(1,n);
long long int sum=0;
for(int i=1;i<=n;i++)
sum+=dist[i];
init(n);
for(int i=1;i<=m;i++){
edge tmp=edges[i];
map[tmp.t].push_back(edge(tmp.t,tmp.f,tmp.c));
}
dijkstra(1,n);
for(int i=1;i<=n;i++)
sum+=dist[i];
printf("%lld\n",sum);
}
}

POJ - 1511 Invitation Cards(Dijkstra变形题)的更多相关文章

  1. POJ 1511 - Invitation Cards (dijkstra优先队列)

    题目链接:http://poj.org/problem?id=1511 就是求从起点到其他点的最短距离加上其他点到起点的最短距离的和 , 注意路是单向的. 因为点和边很多, 所以用dijkstra优先 ...

  2. POJ 1511 Invitation Cards(Dijkstra(优先队列)+SPFA(邻接表优化))

    题目链接:http://poj.org/problem?id=1511 题目大意:给你n个点,m条边(1<=n<=m<=1e6),每条边长度不超过1e9.问你从起点到各个点以及从各个 ...

  3. 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 / ...

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

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

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

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

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

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

  7. [POJ] 1511 Invitation Cards

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

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

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

  9. SPFA算法(2) POJ 1511 Invitation Cards

    原题: Invitation Cards Time Limit: 8000MS   Memory Limit: 262144K Total Submissions: 31230   Accepted: ...

  10. poj 1511 Invitation Cards (最短路)

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

随机推荐

  1. BASH 命令以及使用方法小结

    最近工作中需要写一个Linux脚本,用到了很多BASH命令,为了防止以后忘记,在这里把它们一一记下来.可能会比较乱,随便看看就好了.如果有说的不对的地方也欢迎大家指正. 1,export VAR=.. ...

  2. Mecanim动画模型规范

    面数控制, 以三角面计算 不要超过4边的面 光滑组,法线 单位CM,单位比例 中心点 3DMax:Reset Transform Maya:Freeze Transformation 帧率:30帧 不 ...

  3. Codeforces Round #370(div 2)

    A B C :=w= D:两个人得分互不影响很关键 一种是f[i][j]表示前i轮,分差为j的方案数 明显有f[i][j]=f[i-1][j-2k]+2*f[i-1][j-2k+1]+...+(2k+ ...

  4. 实现解耦-Spring.Net

    spring.net属于IOC(中文名:控制反转)的思想实现. 概念解释: 控制反转概念: 控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来 ...

  5. java中的注解

    注解为程序提供信息,但不是程序本身的组成部分.注解有以下用途: * 为编译器提供信息,相当于C语言中的预编译指令 * 部署时处理,软件工具可以根据注解来生成代码,XML文件等,例如编写servlet, ...

  6. C#利用iComparable接口实现List排序

    List<T>类可以使用Sort()方法对元素排序. Sort()方法定义了几个重载方法,分别是  public void List<T>.Sort(),不带有任何参数的Sor ...

  7. Linux chkconfig命令

    chkconfig命令主要用来更新(启动或停止)和查询系统服务的运行级信息.谨记chkconfig不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接. 使用语法:chkconfig [--ad ...

  8. 强连通 HDU3072

    n个点m条边 m条边 权值 简单点说就是求把所有强连通分量连在一起所需的最小花费 不用双向 图是联通的  cost[] 维护到这里的最小花费求和 #include<stdio.h> #in ...

  9. python中的函数以及递归

    一  函数 函数的组成: def funname(parameters): instructions.... 在探讨函数的定义之前,让我们想想,如果我们写了上千行代码,其实各种变量定义,循环..... ...

  10. an important difference between while and foreach on Perl

    while (<STDIN>) { } # will read from standard input one line at a time foreach (<STDIN>) ...