poj 3463 Sightseeing——次短路计数

题目:http://poj.org/problem?id=3463

当然要给一个点记最短路和次短路的长度和方案。

但往优先队列里放的结构体和vis竟然也要区分0/1,就像把一个点拆成两个点了一样。

不要区分k的fx。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=1005,M=10005;
int T,n,m,head[N],xnt,dis[N][2],f[N][2],st,en;
bool vis[N][2];
struct Ed{
  int next,to,w;
  Ed(int n=0,int t=0,int z=0):next(n),to(t),w(z) {}
}ed[M];
struct Node{
  int bh,dis;bool fx;
  Node(int b=0,int d=0,bool f=0):bh(b),dis(d),fx(f) {}
  bool operator< (const Node &b)const
  {
    return dis>b.dis;
  }
};
void add(int x,int y,int z)
{
  ed[++xnt]=Ed(head[x],y,z);head[x]=xnt;
}
void dj()
{
  memset(vis,0,sizeof vis);memset(dis,1,sizeof dis);
  memset(f,0,sizeof f);
  priority_queue<Node> q;
  dis[st][0]=0;//dis[st][1]
  f[st][0]=1;//!
  q.push(Node(st,0,0));//no push [1]
  while(q.size())
    {
      Node t=q.top();q.pop();int k=t.bh;bool fx=t.fx;
      while(q.size()&&vis[k][fx])t=q.top(),q.pop(),k=t.bh,fx=t.fx;
      if(vis[k][fx])break;vis[k][fx]=1;
      for(int i=head[k],v;i;i=ed[i].next)//不要区分fx,[k][1]也能更新[v][0]!
    {
        int d=dis[k][fx],w=ed[i].w;
          if(d+w<dis[v=ed[i].to][0])
        {
          dis[v][1]=dis[v][0];f[v][1]=f[v][0];
          dis[v][0]=d+w;f[v][0]=f[k][fx];
          q.push(Node(v,dis[v][0],0));
          q.push(Node(v,dis[v][1],1));//!because zj‘s [1] also has been pshp
        }
          else if(d+w==dis[v][0])
        f[v][0]+=f[k][fx];
          else if(d+w<dis[v][1])
        {
          dis[v][1]=d+w;f[v][1]=f[k][fx];
          q.push(Node(v,dis[v][1],1));
        }
          else if(d+w==dis[v][1])
        f[v][1]+=f[k][fx];
    }
    }
}
int main()
{
  scanf("%d",&T);
  while(T--)
    {
      scanf("%d%d",&n,&m);
      memset(head,0,sizeof head);xnt=0;
      int x,y,z;
      for(int i=1;i<=m;i++)
    {
      scanf("%d%d%d",&x,&y,&z);add(x,y,z);
    }
      scanf("%d%d",&st,&en);
      dj();
      if(dis[en][1]==dis[en][0]+1)f[en][0]+=f[en][1];
      printf("%d\n",f[en][0]);
    }
  return 0;
}

原文地址:https://www.cnblogs.com/Narh/p/9275316.html

时间: 2024-10-10 12:39:37

poj 3463 Sightseeing——次短路计数的相关文章

【图论补完计划】poj 3463 (次短路计数 dijkstra)

Sightseeing Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9127   Accepted: 3206 Description Tour operator Your Personal Holiday organises guided bus trips across the Benelux. Every day the bus moves from one city S to another city F. O

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

/* 对dij的再一次理解 每个点依旧永久标记 只不过这里多搞一维 0 1 表示最短路还是次短路 然后更新次数相当于原来的两倍 更新的时候搞一下就好了 */ #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> #define maxn 1010 using namespace std; int T,n,m,num,head[m

poj 3463 Sightseeing (dij 求最短路和次短路并计数)

dijkstra求最短路和次短路的求法和计算  模板 dijkstra求最短路的变形. 外循环要循环2*n-1次,因为dis[n][2]有2*n个状态,而dis[s][0]已经用过一次. 算法: 1.如果比最短路短就更新最短路和次短路. 2.如果和最短路相等,更新最短路的计数. 3.如果和次短路相等,更新次短路的方法数. 4.如果比次短路短,更新次短路. #include<cstdio> #include<iostream> #include<cstring> #inc

poj 3463 Sightseeing(最短路+次短路)

http://poj.org/problem?id=3463 大致题意:给出一个有向图,从起点到终点求出最短路和次短路的条数之和. 解法: 用到的数组:dis[i][0]:i到起点的最短路,dis[i][1]:i到起点的严格次短路 vis[i][0],vis[i][1]:同一维的vis数组,标记距离是否已确定 sum[i][0]:i到起点的最短路条数,sum[i][1]:i到起点的次短路条数 同一维dijkstra,内循环先找出最短的距离(次短路或最短路)d,然后枚举与该点相连的点: if(d

poj 3463 Sightseeing 最短路径数量

题意: 求有向图中最短路和比最短路大1的路径数量. 思路: 需要理解dijkstra算法中dis[n]数组的含义,设cnt[i]表示到点i的最短路径数量,cnt1[i]表示到点i比最短路大1的路径数量.在运行dijkstra算法的过程中每次获得最小dis[i]的时候可以对所有dis[v]+w(v,i)==dis[i]的v做如下更新cnt[i]+=cnt[v],cnt1[i]+=cnt1[v].而当所有值为某数的dis[i]计算完成时也就是对任意i,dis[i]为同一值且不再变化时,可以对这些满足

POJ 3463 Sightseeing (最短路 次短路)

Tour operator Your Personal Holiday organises guided bus trips across the Benelux. Every day the bus moves from one city S to another city F. On this way, the tourists in the bus can see the sights alongside the route travelled. Moreover, the bus mak

(最短路深入)POJ 3463 - Sightseeing

题意: 给一个有向图,计算最短路和比最短路少1的路的条数的和. 分析: 这题真的写死我了. 因为之前很少接触最短路问题,所谓偶尔遇到一次也是套的模板,根本没有细细思考过dijsktra算法.所以栽在了这题上. 这题就是求最短路和次短路. 核心思想在于修改最短路松弛的条件,并且每个节点同时维护最短路和次短路. 很多博主写的很详细,我也不多说了,只是写个博文记录一下自己有多渣,在学习算法的道路上自己真的思考的不够多,也不够努力. 代码: 1 #include <set> 2 #include &l

poj3463 Sightseeing——次短路计数

题目:http://poj.org/problem?id=3463 次短路计数问题,在更新最短路的同时分类成比最短路短.长于最短路而短于次短路.比次短路长三种情况讨论一下,更新次短路: 然而其实不必被"同时"限制,否则就容易像我一开始一样写挂... 像拆点一样把最短路和次短路完全分开,放进 dijkstra 的优先队列里,真是巧妙: 还要注意一点是直接更新最短路之后要把它的次短路也加进优先队列里,因为次短路同时也被更新了. 代码如下: #include<iostream>

POJ 3463 - Sightseeing

题意:告诉你那n个点以及m条单向边.询问你从s点到e点最短路和比最短路长度大一的路一共有多少条. 思路:dijkstra变形.分别从起点和终点求一边dijkstra.用cnt数组分别记录从起点到达第i个点且长度为最短长度的路径数以及从原点到达第i个点且长度为最短长度的路径数._cnt数组记录到第i个节点的距离为最短距离+1的路径数.注意_cnt[i]所记录的路径只包括第i个节点的pre节点为最短路而pre节点到第i个节点不是最短路的情况.这样可以防止重复计算. 具体的松弛操作:设u为未经过的节点