POJ 3463 Sightseeing dijkstra
来源:互联网 发布:用ps做淘宝主图 编辑:程序博客网 时间:2024/06/08 07:50
题目链接:http://poj.org/problem?id=3463
题意:给定一个图,找最短路和比最短路多1的路的条数。
思路1:将次短路也当作一种“最短”的状态,去扩展状态。这样每个点就有两种属性,次短和最短。记录次短路条数和记录最短路条数类似。
/*
我们知道Dijkstra就是不断地用已经确定最短路的节点(黑色)去松弛未确定的点(白色),
用数学归纳法很容易证明这是正确的。它的核心思想就是某个节点的最短路一定是由它前
驱节点的最短路扩展来的。那么对于次短路也可以类似的看:一个节点的次短路一定是由
它前驱节点的最短路 or 次短路扩展而来的。那么我们就可以把节点分成两层处理:一层
处理、存储最短路,另一层处理、存储次短路。这样, 用于记录状态的数组变成了二维,
放进堆中的状态也必须是”二维”的, 这里的”二维”并不是要你开个二维数组, 而是需要在
放入堆中的结构体里多加一个标记变量, 用于标识到底是最短路还是次短路, 当然, 用于
标记已经确定最短路、次短路的点的closed表同样要变成二维的。
*/
#include<cstdio>#include<queue>#include<iostream>#include<vector>#include<map>#include<cstring>#include<string>#include<set>#include<stack>#include<algorithm>#define cle(a) memset(a,0,sizeof(a))#define inf(a) memset(a,0x3f,sizeof(a))#define ll long long#define Rep(i,a,n) for(int i=a;i<=n;i++)using namespace std;const int INF = ( 2e9 ) + 2;const ll maxn = 1e3+10;struct edge{ int v,w,next;}e[20*maxn];struct node{ int u,d,flag; bool operator < (const node &b)const { return d>b.d; }};int tot,head[maxn],d[maxn][2],cnt[maxn][2],vis[maxn][2];void addedge(int u,int v,int w){ e[tot].v=v; e[tot].w=w; e[tot].next=head[u]; head[u]=tot++;}void dijkstra(int s,int t,int n){ for(int i=1;i<=n;i++) for(int j=0;j<2;j++) { d[i][j]=INF; vis[i][j]=0; } cnt[s][0]=cnt[s][1]=1; d[s][0]=0; priority_queue<node> q; q.push(node{s,0,0}); while(!q.empty()) { node a=q.top();q.pop(); int u=a.u; if(vis[u][a.flag])continue; vis[u][a.flag]=1; for(int i=head[u];i!=-1;i=e[i].next) { int v=e[i].v,w=e[i].w; if(d[v][0]>a.d+w) { d[v][1]=d[v][0]; cnt[v][1]=cnt[v][0]; d[v][0]=a.d+w; cnt[v][0]=cnt[u][a.flag]; q.push(node{v,d[v][0],0}); q.push(node{v,d[v][1],1}); } else if(d[v][0]==a.d+w) { cnt[v][0]+=cnt[u][a.flag]; } else if(d[v][1]>a.d+w) { d[v][1]=a.d+w; cnt[v][1]=cnt[u][a.flag]; q.push(node{v,d[v][1],1}); } else if(d[v][1]==a.d+w) { cnt[v][1]+=cnt[u][a.flag]; } } } if(d[t][0]+1!=d[t][1]) printf("%d\n",cnt[t][0]); else printf("%d\n",cnt[t][0]+cnt[t][1]);}int main(){ int t; scanf("%d",&t); while(t--) { int n,m; tot=0; memset(head,-1,sizeof(head)); scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); } int s,t; scanf("%d%d",&s,&t); dijkstra(s,t,n); }}
思路2:从最短路上选择一个点,去“替换”最短路上的边,看能否凑成比最短路多1的路。
#include<cstdio>#include<queue>#include<iostream>#include<vector> #include<map>#include<cstring>#include<string>#include<set>#include<stack>#include<algorithm>#define cle(a) memset(a,0,sizeof(a))#define inf(a) memset(a,0x3f,sizeof(a))#define ll long long#define Rep(i,a,n) for(int i=a;i<=n;i++)using namespace std;const int INF = ( 2e9 ) + 2;const ll maxn = 1e3+10;struct edge{ int v,w,next;}e[maxn*20];struct node{ int u,d; bool operator < (const node &b)const { return d>b.d; }};int head[maxn],vis[maxn],d2[maxn],d1[maxn],cnt1[maxn],cnt2[maxn],tot;void addedge(int u,int v,int w){ e[tot].v=v; e[tot].w=w; e[tot].next=head[u]; head[u]=tot++; e[tot].v=u; e[tot].w=w; e[tot].next=head[v]; head[v]=tot++;}void dijkstra(int s,int n,int cnt[],int d[],int flag){ for(int i=1;i<=n;i++)d[i]=INF; d[s]=0; memset(vis,0,sizeof(vis)); priority_queue<node> q; q.push(node{s,0}); cnt[s]=1; while(!q.empty()) { node a=q.top();q.pop(); int u=a.u; if(vis[u])continue; vis[u]=1; for(int i=head[u];i!=-1;i=e[i].next) { if((i&1)!=flag)continue; int v=e[i].v,w=e[i].w; if(vis[v])continue; if(d[v]>d[u]+w) { d[v]=d[u]+w; cnt[v]=cnt[u]; q.push(node{v,d[v]}); } else if(d[v]==d[u]+w) { cnt[v]+=cnt[u]; } } }}int cul(int mindis,int n){ int ans=0; for(int i=1;i<=n;i++) { if(d1[i]+d2[i]!=mindis) continue; for(int j=head[i];j!=-1;j=e[j].next) { if((j&1)!=0)continue; int w=e[j].w; int v=e[j].v; if(d1[i]+d2[v]+w==mindis+1) ans+=cnt1[i]*cnt2[v]; } } return ans;} int main(){ int T; scanf("%d",&T); while(T--) { int n,m; tot=0; memset(vis,0,sizeof(vis)); memset(head,-1,sizeof(head)); memset(d1,0,sizeof(d1)); memset(d2,0,sizeof(d2)); scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); } int s,f; scanf("%d%d",&s,&f); dijkstra(s,n,cnt1,d1,0); dijkstra(f,n,cnt2,d2,1); printf("%d\n",cul(d1[f],n)+cnt1[f]); }}
阅读全文
0 0
- POJ 3463 Sightseeing dijkstra
- POJ 3463 Sightseeing dijkstra
- POJ 3463 Sightseeing (次短路,Dijkstra拓展)
- 【Dijkstra+邻接表求次短路】POJ Sightseeing 3463
- 通过POJ 3463 Sightseeing(dijkstra)彻底理解优先队列优化的dijkstra算法
- POJ 3463 Sightseeing
- ACM POJ 3463 Sightseeing
- poj 3463 Sightseeing
- poj 3463 Sightseeing
- poj 3463 Sightseeing
- POJ 3463 Sightseeing
- poj 3463 Sightseeing
- POJ 3463: Sightseeing
- POJ 3463 Sightseeing
- POJ 3463 Sightseeing
- poj-3463 Sightseeing
- POJ 3463 Sightseeing
- Poj 3463 Sightseeing
- Win7快捷键17
- 织梦(dedecms)后台删除文章后台还有分页显示解决方法
- Spring Boot Admin
- spring cloud系列一 搭建配置服务器(分布式配置管理)configserver
- 新特性总结-JDK1.8
- POJ 3463 Sightseeing dijkstra
- 2506-完美网络
- 找不到类库
- Java多线程一般用法
- 神经网络入门
- 打造万能的ListView GridView 适配器
- 读取机器人反馈数据,控制机器人状态
- Oracle字符分隔函数(split)
- 超时处理器封装