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]);    }}
原创粉丝点击