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 ...
随机推荐
- Flash Builder快捷键
代码助手:Ctrl+Space(简体中文操作系统是Alt+/)快速修正:Ctrl+1单词补全:Alt+/打开外部Java文档:Shift+F2 显示搜索对话框:Ctrl+H快速Outline:Ctrl ...
- 文件泄露&php代码审计
这道题,还是很不错的.卡在了token绕过那里,不得已看了别人的writeUp,才做出来,惭愧! 但还是想写写WriteUp做一下记录! 首先是打开题目,习惯性查看源码,发现了点蛛丝马迹 知道了,管理 ...
- C和指针笔记 3.7 存储类型
变量的破碎类型是指存储变量值的内存类型.变量的存储类型决定变量何时创建.何时销毁以及它的值将保持多久. 有三个地方可以用于存在变量:普通内存.运行时堆栈.硬件寄存器. 变量的缺省存储类型取决于它的声明 ...
- js模拟手机触摸屏
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- 26Spring_的注解实际应用_关键整理一下之前的注解
写一个银行转账案例, 案例结构如下:
- Windows Phone 简介
中文官网 https://dev.windowsphone.com/zh-cn Windows Phone SDK 7.1 http://www.microsoft.com/zh-cn/downloa ...
- 【WPF】Winform调用WPF窗体注意事项
1.需要添加一些引用 2.调用处使用如下方法进行调用 Window win= new Window(); ElementHost.EnableModelessKeyboardInterop(win) ...
- windows 批处理把所有java源码导入一个txt文件中
首先在src下搜*.java,把搜到的文件全拷出来放在allsrc目录下, 然后在allsrc目录下建个run.bat,键入以下内容for %%i in (*.java) do type %%i&g ...
- php基础33:正则匹配-perl
<?php //1.搜索数组中的相匹配的字符串 //preg_grep() 返回一个数组 $language = array("php","asp",&q ...
- JS结合DOM事件的例子
// 这是初始文字 右边是一个测试文本框: 鼠标划过.点击.松开上面的文字都会有不同的效果,鼠标光标移到.离开文本框也会有不同的效果. 首先新建一个html文件 <!DOCTYPE html&g ...