POJ - 1511 Invitation Cards(Dijkstra变形题)
题意:
给定一个有向图,求从源点到其他各点的往返最短路径和。且这个图有一个性质:任何一个环都会经过源点。
图中的节点个数范围: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变形题)的更多相关文章
- POJ 1511 - Invitation Cards (dijkstra优先队列)
题目链接:http://poj.org/problem?id=1511 就是求从起点到其他点的最短距离加上其他点到起点的最短距离的和 , 注意路是单向的. 因为点和边很多, 所以用dijkstra优先 ...
- POJ 1511 Invitation Cards(Dijkstra(优先队列)+SPFA(邻接表优化))
题目链接:http://poj.org/problem?id=1511 题目大意:给你n个点,m条边(1<=n<=m<=1e6),每条边长度不超过1e9.问你从起点到各个点以及从各个 ...
- 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 / ...
- POJ 1511 Invitation Cards(单源最短路,优先队列优化的Dijkstra)
Invitation Cards Time Limit: 8000MS Memory Limit: 262144K Total Submissions: 16178 Accepted: 526 ...
- DIjkstra(反向边) POJ 3268 Silver Cow Party || POJ 1511 Invitation Cards
题目传送门 1 2 题意:有向图,所有点先走到x点,在从x点返回,问其中最大的某点最短路程 分析:对图正反都跑一次最短路,开两个数组记录x到其余点的距离,这样就能求出来的最短路以及回去的最短路. PO ...
- poj 1511 Invitation Cards(最短路中等题)
In the age of television, not many people attend theater performances. Antique Comedians of Malidine ...
- [POJ] 1511 Invitation Cards
Invitation Cards Time Limit: 8000MS Memory Limit: 262144K Total Submissions: 18198 Accepted: 596 ...
- POJ 1511 Invitation Cards (最短路spfa)
Invitation Cards 题目链接: http://acm.hust.edu.cn/vjudge/contest/122685#problem/J Description In the age ...
- SPFA算法(2) POJ 1511 Invitation Cards
原题: Invitation Cards Time Limit: 8000MS Memory Limit: 262144K Total Submissions: 31230 Accepted: ...
- poj 1511 Invitation Cards (最短路)
Invitation Cards Time Limit: 8000MS Memory Limit: 262144K Total Submissions: 33435 Accepted: 111 ...
随机推荐
- 用PHP+H5+Boostrap做简单的音乐播放器(进阶版)
前言:之前做了一个音乐播放器(纯前端),意外的受欢迎,然后有人建议我把后台一起做了,正好也想学习后台,所以学了两天php(不要吐槽我的速度,慢工出细活嘛~)然后在之前的基础上也又完善了一些功能,所以这 ...
- <实训|第十一天>学习一下linux中的进程,文件查找,文件压缩与IO重定向
[root@localhost~]#序言 在今后的工作中,运维工程师每天的例行事务就是使用free -m,top,uptime,df -h...每天都要检查一下服务器,看看是否出现异常.那么今天我们就 ...
- 基于DDD的.NET开发框架 - ABP依赖注入
返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...
- GitHub 上一份很受欢迎的前端代码优化指南-强烈推荐收藏
看到一份很受欢迎的前端代码指南,根据自己的理解进行了翻译,但能力有限,对一些JS代码理解不了,如有错误,望斧正. HTML 语义化标签 HTML5 提供了很多语义化元素,更好地帮助描述内容.希望你能从 ...
- [POJ2404]Jogging Trails(中国旅行商问题)(一般图的匹配——状压DP)
题目:http://poj.org/problem?id=2404 题意:有个n(n<=15)的点和m条无向边,每条边都有自己的权值.现在你要从某个点出发,每条边可以经过多次但要保证每条边至少走 ...
- [BZOJ1263][SCOI2006]整数划分(数学+高精度)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1263 分析:数学老师上课讲过啦= =,就是尽可能3越多越好.然后就写个高精度就行了.
- Vmware player 12
免费版的虚拟机Vmware,体积小.运行快速... 官方下载界面 下载地址: http://yunpan.cn/cm5smywVvqS8V 访问密码 35ac 官方下载:点击下载
- 【Python】[函数式编程]高阶函数,返回函数,装饰器,偏函数
函数式编程高阶函数 就是把函数作为参数的函数,这种抽象的编程方式就是函数式编程.--- - -跳过,不是很理解,汗 - ---
- 【Python】 [基础] 条件判断 与 循环 与dict和set
# 条件判断 elif: else if 的作用 注意: : [冒号]BMI =w/(h*h) if BMI<15: print('较轻')elif BMI<25: prin ...
- android 一条线
还在为布局的时候做不出来一条细细的线而烦恼么? 哈哈,自从知道了写法腰也不酸了,腿也不疼了!一口气写100行!! <View android:layout_height="1px&qu ...