poj 3463 最短路与次短路&&统计个数
题意:求最短路和比最短路长度多1的次短路的个数
本来想图(有)方(模)便(版)用spfa的,结果妹纸要我看看dijkstra怎么解....
写了三遍orz
Ver1.0:堆优化+邻接表,WA
//不能用堆优化+邻接表,因为需要处理dis[i][0]和dis[i][1]两套,如果都挤到一个堆里就乱套了 #include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <vector>
using namespace std;
const int Ni = ;
const int INF = <<;
struct node
{ //eg[i].x eg[i].d i:start x:end d:distance
int x,d;
node(){}
node(int a,int b){x=a;d=b;}
bool operator < (const node & a) const //用于优先队列, 取距离原点最近的点
{
if(d==a.d) return x<a.x;
else return d > a.d;
}
};
vector<node> eg[Ni];
int dis[Ni][],cnt[Ni][],n,T; void Dijkstra(int s) //1.比最短路短2.等于最短路3.长于最短路但短于次短路4.等于次短路
{
memset(dis,,sizeof(dis));
memset(cnt,,sizeof(cnt)); int i;
for(i=;i<=n;i++)
{
dis[i][]=INF;
dis[i][]=INF;
}
dis[s][]=;
dis[s][]=;
priority_queue<node> q; //q:优先队列,用来取离原点最近的顶点
q.push(node(s,dis[s][])); //初始只有一个原点自己
while(!q.empty())
{
node x=q.top();q.pop();
for(i=;i<eg[x.x].size();i++)
{
node y=eg[x.x][i];
if(dis[y.x][]>x.d+y.d) //
{
cnt[y.x][]=;
cnt[y.x][]=;
dis[y.x][]=dis[y.x][];
dis[y.x][]=x.d+y.d;
q.push(node(y.x,dis[y.x][]));
}
else if (dis[y.x][]==x.d+y.d) //
{
cnt[y.x][]++;
}
else if ((dis[y.x][]<x.d+y.d)&&(x.d+y.d<dis[y.x][])) //
{
cnt[y.x][]=;
dis[y.x][]=x.d+y.d;
}
else if (x.d+y.d==dis[y.x][]) //
{
cnt[y.x][]++;
}
}
}
} void debug()
{
cout<<"Debug only"<<endl;
for (int i=;i<=n;i++)
printf("%d - %d %d - %d %d\n",i,dis[i][],cnt[i][],dis[i][],cnt[i][]);
cout<<ans1<<" "<<ans2<<endl; } int main()
{
scanf("%d",&T);
while (T--)
{
int a,b,d,m,k,st;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) eg[i].clear();
while(m--)
{
scanf("%d%d%d",&a,&b,&d);
eg[a].push_back(node(b,d));
}
scanf("%d %d",&k,&st);
Dijkstra(k); debug1(); int t1=dis[st][],t2=dis[st][],ans1=cnt[st][],ans2;
if (t2-t1==)
ans2=cnt[st][];
else ans2=;
printf("%d\n",ans1+ans2);
} return ;
}
Ver2.0:邻接矩阵,WA
//不能用邻接矩阵,因为会有重边 #include <iostream>
#include <cstring>
using namespace std;
#define MAXINT 9999999 int minx,minj,x,y,t,k,n,m,tmp,st,flag;
int v[][],d[][],cnt[][],a[][]; int main()
{
int T;
cin>>T;
while (T--)
{
cin>>n>>m;
memset(a,,sizeof(a));
memset(d,MAXINT,sizeof(d));
memset(v,,sizeof(v));
memset(cnt,,sizeof(cnt)); for (int i=;i<=m;i++)
{
cin>>x>>y>>t;
a[x][y]=t;
}
cin>>k>>st;
d[k][]=; //d[k][2]=0;
cnt[k][]=; // cnt[k][2]=1; for (int i=;i<=*n;i++)
{
minx=MAXINT;
for (int j=;j<=n;j++)
{
if ((v[j][]==)&&(d[j][]<minx))
{
minx=d[j][];
minj=j;
flag=;
}
if ((v[j][]==)&&(d[j][]<minx))
{
minx=d[j][];
minj=j;
flag=;
}
}
v[minj][flag]=;
for (int j=;j<=n;j++)
// if ((v[j][1]==0)&&(a[minj][j]>0))
if (a[minj][j]>)
{
tmp=minx+a[minj][j]; if (tmp<d[j][])
{
d[j][]=d[j][];
d[j][]=tmp;
cnt[j][]=cnt[j][];
cnt[j][]=cnt[minj][flag];
}
else if (tmp==d[j][])
{
cnt[j][]+=cnt[minj][flag];
}
else if (tmp<d[j][])
{
d[j][]=tmp;
cnt[j][]=cnt[minj][flag];
}
else if (tmp==d[j][])
{
cnt[j][]+=cnt[minj][flag];
}
}
} for (int i=;i<=n;i++)
cout<<d[i][]<<" "<<cnt[i][]<<" = "<<d[i][]<<" "<<cnt[i][]<<endl;
cout<<endl;
int t1=d[st][],t2=d[st][],ans1=cnt[st][],ans2;
if (t2==t1+) ans2=cnt[st][]; else ans2=;
cout<<ans1+ans2<<endl;
}
return ;
}
Ver3.0:朴素n^2算法+邻接表 AC
#include <stdio.h>
#include <string.h>
#define INF 999999 struct node
{
int to,dat;
}edge[][]; int cnt[][],d[][],vis[][];
int x,y,z,n,m,T,st,ed; void insert_node(int x,int y,int z)
{
edge[x][].dat++;
int tmp=edge[x][].dat;
edge[x][tmp].to=y;
edge[x][tmp].dat=z;
} void dijkstra()
{
memset(vis,,sizeof(vis));
memset(d,INF,sizeof(d));
memset(cnt,,sizeof(cnt));
d[st][]=;
cnt[st][]=; for (int i=;i<=*n;i++)
{
int minj,flag,minx=INF;
for (int j=;j<=n;j++)
if ((vis[j][]==)&&(d[j][]<minx))
{
minx=d[j][];
minj=j;
flag=;
}
else if ((vis[j][]==)&&(d[j][]<minx))
{
minx=d[j][];
minj=j;
flag=;
}
vis[minj][flag]=;
int tmp=edge[minj][].dat;
for (int j=;j<=tmp;j++)
{
int yy=edge[minj][j].to;
int zz=edge[minj][j].dat;
//if (vis[yy][flag]==0)
//{
int tm=minx+zz;
if (tm<d[yy][])
{
d[yy][]=d[yy][];
cnt[yy][]=cnt[yy][];
d[yy][]=tm;
cnt[yy][]=cnt[minj][flag];
}
else if (tm==d[yy][])
{
cnt[yy][]+=cnt[minj][flag];
}
else if (tm<d[yy][])
{
d[yy][]=tm;
cnt[yy][]=cnt[minj][flag];
}
else if (tm==d[yy][])
{
cnt[yy][]+=cnt[minj][flag];
}
//} } }
} int main()
{
// freopen("in.txt","r",stdin); scanf("%d",&T);
while (T--)
{
memset(edge,,sizeof(edge));
scanf("%d %d",&n,&m);
for (int i=;i<=m;i++)
{
scanf("%d %d %d",&x,&y,&z);
insert_node(x,y,z);
}
scanf("%d %d",&st,&ed); /*
for (int i=1;i<=n;i++)
for (int j=1;j<=edge[i][0].dat;j++)
printf("Debug: %d -> %d = %d\n",i,edge[i][j].to,edge[i][j].dat);
*/ dijkstra(); int tx,ty,ans2,ans1;
tx=d[ed][]; ty=d[ed][];
ans1=cnt[ed][];
if (ty-tx==) ans2=cnt[ed][];
else ans2=;
// printf("%Debug: %d %d %d %d\n",tx,ty,ans1,ans2);
printf("%d\n",ans1+ans2);
}
return ;
}
邻接表很少用到都不大会写了>_<
dij松弛的条件改变下,有四种情况
1.比最短路短2.等于最短路3.长与最短路但短于次短路4.等于次短路
d[i][0]记最短路, d[i][1]记次短路
注意这里:
int tm=minx+zz;
if (tm<d[yy][])
{
d[yy][]=d[yy][];
cnt[yy][]=cnt[yy][];
d[yy][]=tm;
cnt[yy][]=cnt[minj][flag];
}
else if (tm==d[yy][])
{
cnt[yy][]+=cnt[minj][flag]; //因为松弛操作是从minj点开始的
//(d[minj]+a[minj,j]<d[j])
//所以记录cnt的时候要+=cnt[minj][flag]
//一开始以为直接+1就行,WA了
//前面的cnt[yy][0]=cnt[minj][flag]同理
}
else if (tm<d[yy][])
{
d[yy][]=tm;
cnt[yy][]=cnt[minj][flag];
}
else if (tm==d[yy][])
{
cnt[yy][]+=cnt[minj][flag];
}
Reference:
http://blog.csdn.net/wmn_wmn/article/details/7376707
http://www.cnblogs.com/Missa/archive/2012/08/31/2665244.html
poj 3463 最短路与次短路&&统计个数的更多相关文章
- poj 3463/hdu 1688 求次短路和最短路个数
http://poj.org/problem?id=3463 http://acm.hdu.edu.cn/showproblem.php?pid=1688 求出最短路的条数比最短路大1的次短路的条数和 ...
- poj 3463 Sightseeing(次短路+条数统计)
/* 对dij的再一次理解 每个点依旧永久标记 只不过这里多搞一维 0 1 表示最短路还是次短路 然后更新次数相当于原来的两倍 更新的时候搞一下就好了 */ #include<iostream& ...
- poj 3463 Sightseeing( 最短路与次短路)
http://poj.org/problem?id=3463 Sightseeing Time Limit: 2000MS Memory Limit: 65536K Total Submissio ...
- poj 3463 Sightseeing——次短路计数
题目:http://poj.org/problem?id=3463 当然要给一个点记最短路和次短路的长度和方案. 但往优先队列里放的结构体和vis竟然也要区分0/1,就像把一个点拆成两个点了一样. 不 ...
- POJ - 3463 Sightseeing 最短路计数+次短路计数
F - Sightseeing 传送门: POJ - 3463 分析 一句话题意:给你一个有向图,可能有重边,让你求从s到t最短路的条数,如果次短路的长度比最短路的长度多1,那么在加上次短路的条数. ...
- POJ 3463 有向图求次短路的长度及其方法数
题目大意: 希望求出走出最短路的方法总数,如果次短路只比最短路小1,那也是可取的 输出总的方法数 这里n个点,每个点有最短和次短两种长度 这里采取的是dijkstra的思想,相当于我们可以不断找到更新 ...
- poj 3463 最短路+次短路
独立写查错不能,就是维护一个次短路的dist 题意:给定一个有向图,问从起点到终点,最短路+比最短路距离长1的路的个数. Sample Input25 81 2 31 3 21 4 52 3 12 5 ...
- poj 3463 次短路
题意:给定一个有向图,问从起点到终点,最短路+比最短路距离长1的路的个数. 当年数据结构课程设计用A*做过,现在忘光了,2333 #include<stdio.h> #include< ...
- POJ 3463 Sightseeing (次短路)
题意:求两点之间最短路的数目加上比最短路长度大1的路径数目 分析:可以转化为求最短路和次短路的问题,如果次短路比最短路大1,那么结果就是最短路数目加上次短路数目,否则就不加. 求解次短路的过程也是基于 ...
- POJ 3463 Sightseeing 【最短路与次短路】
题目 Tour operator Your Personal Holiday organises guided bus trips across the Benelux. Every day the ...
随机推荐
- Linux搭建PHP+MySQL+Apache环境
环境: CentOS 6.4 MySQL详细安装可参考:http://www.cnblogs.com/yangxia-test/archive/2012/11/12/2766237.html Apac ...
- JAVA NIO概述(一):I/O模型
NIO是jdk1.4加入的新功能,我们一般成为非阻塞IO,在1.4之前,JAVA中的都是BIO(堵塞IO),BIO有以下几个缺点: 没有数据缓冲区,I/O性能存在问题 没有C/C++中channel( ...
- 书籍推荐 《移动Web手册》 奇舞团
书籍推荐 <移动Web手册> 奇舞团
- js原生捕鱼达人(二)
昨天写到构造炮弹,有点小bug不知道大家发现没有,今天继续昨天的步骤 7>构造炮弹 思路和前面都是一样一样的 注意构造函数中需要考虑的属性 和 构造函数的原型上面的方法 <sc ...
- Eclipse添加注释简介
(1)在方法或者属性上面添加注释:在方法或者属性字段的上面一行输/**,然后回车.一般情况下添加的注释格式如下所示,当然注释的格式是可以修改的: 1 2 3 4 5 /** * @param ...
- C# 结构体
1,结构体不能出现在继承关系中,除了继承接口. 结构体不能继承类或结构,也不能被类或结构继承,只可以继承接口. 2,struct不能定义默认构造函数(无参构造函数),也不能定义析构函数.class对这 ...
- 20145222黄亚奇《Java程序设计》实验四实验报告
20145222<Java程序设计>第四次实验报告 实验四 Android环境搭建 实验内容 1.搭建Android环境 2.运行Android 3.修改代码,能输出学号 实验步骤 搭建A ...
- 简便的自动布局,对UIStackView的个人理解!
序言: 更新了很久的Linux,我怕朋友们都视觉疲劳了,今天就更新在学ios开发时候,对一些知识点的理解.希望各位会喜欢! 正文: UIStackView 类提供了一个高效的接口用于平铺一行或一列的视 ...
- .NET领域最为流行的IOC框架之一Autofac
一.前言 Autofac是.NET领域最为流行的IOC框架之一,微软的Orchad开源程序使用的就是Autofac,Nopcommerce开源程序也是用的Autofac. Orchad和Nopcomm ...
- 开源搜索引擎Iveely 0.8.0发布,终见天日
这是一篇博客,不是,这是一篇开源人的心酸和喜悦,没有人可以理解我们的心情,一路的辛酸一路的艰辛,不过还好,在大家的支持下,总算是终见天日,谢谢那些给予我们无私帮助的朋友.您的支持,依然是我们无限的动力 ...