题意:求最短路和比最短路长度多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 最短路与次短路&&统计个数的更多相关文章

  1. poj 3463/hdu 1688 求次短路和最短路个数

    http://poj.org/problem?id=3463 http://acm.hdu.edu.cn/showproblem.php?pid=1688 求出最短路的条数比最短路大1的次短路的条数和 ...

  2. poj 3463 Sightseeing(次短路+条数统计)

    /* 对dij的再一次理解 每个点依旧永久标记 只不过这里多搞一维 0 1 表示最短路还是次短路 然后更新次数相当于原来的两倍 更新的时候搞一下就好了 */ #include<iostream& ...

  3. poj 3463 Sightseeing( 最短路与次短路)

    http://poj.org/problem?id=3463 Sightseeing Time Limit: 2000MS   Memory Limit: 65536K Total Submissio ...

  4. poj 3463 Sightseeing——次短路计数

    题目:http://poj.org/problem?id=3463 当然要给一个点记最短路和次短路的长度和方案. 但往优先队列里放的结构体和vis竟然也要区分0/1,就像把一个点拆成两个点了一样. 不 ...

  5. POJ - 3463 Sightseeing 最短路计数+次短路计数

    F - Sightseeing 传送门: POJ - 3463 分析 一句话题意:给你一个有向图,可能有重边,让你求从s到t最短路的条数,如果次短路的长度比最短路的长度多1,那么在加上次短路的条数. ...

  6. POJ 3463 有向图求次短路的长度及其方法数

    题目大意: 希望求出走出最短路的方法总数,如果次短路只比最短路小1,那也是可取的 输出总的方法数 这里n个点,每个点有最短和次短两种长度 这里采取的是dijkstra的思想,相当于我们可以不断找到更新 ...

  7. poj 3463 最短路+次短路

    独立写查错不能,就是维护一个次短路的dist 题意:给定一个有向图,问从起点到终点,最短路+比最短路距离长1的路的个数. Sample Input25 81 2 31 3 21 4 52 3 12 5 ...

  8. poj 3463 次短路

    题意:给定一个有向图,问从起点到终点,最短路+比最短路距离长1的路的个数. 当年数据结构课程设计用A*做过,现在忘光了,2333 #include<stdio.h> #include< ...

  9. POJ 3463 Sightseeing (次短路)

    题意:求两点之间最短路的数目加上比最短路长度大1的路径数目 分析:可以转化为求最短路和次短路的问题,如果次短路比最短路大1,那么结果就是最短路数目加上次短路数目,否则就不加. 求解次短路的过程也是基于 ...

  10. POJ 3463 Sightseeing 【最短路与次短路】

    题目 Tour operator Your Personal Holiday organises guided bus trips across the Benelux. Every day the ...

随机推荐

  1. mysql order by 出现Using filesort的解决办法

    http://blog.csdn.net/yangyu112654374/article/details/4251624 比如一条sql语句 select * from TABLE1 where A1 ...

  2. ios开发中如何隐藏各种bar

    转载自http://www.cnblogs.com/lovecode/articles/2234557.html 状态条Status Bar [UIApplication sharedApplicat ...

  3. windows系统命令服务安装卸载

    安装: sc create PDW.CHM.WebAPI binPath= "%~dp0PDW.CHM.WebAPI.exe" start= autosc start PDW.CH ...

  4. Linux ssh登录和软件安装详解

    阿哲Style   Linux第一天 ssh登录和软件安装详解 Linux学习第一天 操作环境: Ubuntu 16.04 Win10系统,使用putty_V0.63 本身学习Linux就是想在服务器 ...

  5. rsyslog 日志统一搜集&message格式

        日志格式修改: http://jiechao2012.blog.51cto.com/3251753/1143762 http://yulei7633.blog.51cto.com/149275 ...

  6. JS 之匿名函数

    匿名函数以及闭包 匿名函数就是没有名字的函数.闭包是指有权访问另一个函数作用域中的变量的函数.创建闭包的常见方式是在一个函数的内部创建另一个函数.闭包会携带包含它的函数的作用域,因此会比其他函数占用更 ...

  7. 获取元素的xpath, 转换xpath为csspath进行jQuery元素获取

    获取元素的xpath, 转换xpath为csspath进行jQuery元素获取 博客分类: 编程心得 jQueryCSSHTML  var $shadow = new Object(); /** 获取 ...

  8. Matlab 用fread、fwrite实现大文件读写

    最近在分析一个35G的大数据文件,猛一看,是不是很吓人啊,不过还好,师兄写文件的格式非常规范,读取数据来也就很方便了,主要是使用了读写文件的两个函数fread和fwrite,下面用matlab简单尝试 ...

  9. struct2cell

    函数功能:把结构体转换为元胞数组. 语法格式: c = struct2cell(s) 如果s是m*n(m行n列)的二维的结构体数组,每个结构体含有p个域,则转换得到一个p*m*n的元胞数组c. 如果s ...

  10. 九度oj-1003-Java

    题目描述: 给定两个整数A和B,其表示形式是:从个位开始,每三位数用逗号","隔开. 现在请计算A+B的结果,并以正常形式输出. 输入: 输入包含多组数据数据,每组数据占一行,由两 ...