HDU6181-Two Paths【A*算法or次短路】

来源:互联网 发布:sql server2012r2下载 编辑:程序博客网 时间:2024/06/07 04:37

Two Paths

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 153428/153428 K (Java/Others)
Total Submission(s): 190 Accepted Submission(s): 113

Problem Description
You are given a undirected graph with n nodes (numbered from 1 to n) and m edges. Alice and Bob are now trying to play a game.
Both of them will take different route from 1 to n (not necessary simple).
Alice always moves first and she is so clever that take one of the shortest path from 1 to n.
Now is the Bob’s turn. Help Bob to take possible shortest route from 1 to n.
There’s neither multiple edges nor self-loops.
Two paths S and T are considered different if and only if there is an integer i, so that the i-th edge of S is not the same as the i-th edge of T or one of them doesn’t exist.

Input
The first line of input contains an integer T(1 <= T <= 15), the number of test cases.
The first line of each test case contains 2 integers n, m (2 <= n, m <= 100000), number of nodes and number of edges. Each of the next m lines contains 3 integers a, b, w (1 <= a, b <= n, 1 <= w <= 1000000000), this means that there’s an edge between node a and node b and its length is w.
It is guaranteed that there is at least one path from 1 to n.
Sum of n over all test cases is less than 250000 and sum of m over all test cases is less than 350000.

Output
For each test case print length of valid shortest path in one line.

Sample Input
2
3 3
1 2 1
2 3 4
1 3 3
2 1
1 2 1

Sample Output
5
3
Hint

For testcase 1, Alice take path 1 - 3 and its length is 3, and then Bob will take path 1 - 2 - 3 and its length is 5.
For testcase 2, Bob will take route 1 - 2 - 1 - 2 and its length is 3

Source
2017 Multi-University Training Contest - Team 10

题目大意:1n的次短路。
解题思路:A算法可以用来求第k短路,当然也可以用来求次短路。
k短路可以理解为第k次走到终点,那就相当于是终点被找到k次,即出队k次。利用A算法,首先求出其他点到des的最短距离,然后用基于BFS的优先队列A算法求f(i)=g(i)+h(i),其中h(i)表示ides的最短路,g(i)表示从srci的路径长度,每次取出f(i)值最小的,当第k次取出t时即求出第k短路。
注: A算法的题目可以看POJ2449

另解:此题也可以直接用求次短路的方法(在Dijkstra上进行少许修改)解决。到某个顶点v的次短路要么是到其他某个顶点u的最短路再加上uv的边,要么是到u的次短路再加上uv的边。对于每个顶点,我们记录的不仅仅是最短距离,还有次短距离。在跑Dijkstra时,不断更新这两个距离即可。
注:次短路算法的题目可以看POJ3255

A解法:

#include<iostream>#include<cstdio>#include<queue>#include<cstring>using namespace std;typedef long long LL;const LL INF=1e18;const int MAXN=1e5+5;int head[MAXN],head1[MAXN];LL dis[MAXN];bool vis[MAXN];int n,m,tot,st,en,k;struct Edge{    int u,v,nxt,nxt1;    LL c;    Edge(){}    Edge(int _u,int _v,LL _c):u(_u),v(_v),c(_c){}}e[MAXN*2];struct qnode{    int v;    LL c;    qnode(){}    qnode(int _v,LL _c):v(_v),c(_c){}    bool operator < (const qnode& rhs) const    {        return c+dis[v]>rhs.c+dis[rhs.v];    }};void addedge(int u,int v,LL c){    e[tot]=Edge(u,v,c);    e[tot].nxt=head[u];head[u]=tot;    e[tot].nxt1=head1[v];head1[v]=tot++;}void dij(int src){    memset(vis,false,sizeof(vis));    for(int i=1;i<=n;i++) dis[i]=INF;    dis[src]=0;    priority_queue<qnode> que;    que.push(qnode(src,0));    while(!que.empty())    {        qnode pre=que.top(); que.pop();        if(vis[pre.v]) continue;        vis[pre.v]=true;        for(int i=head1[pre.v];i!=-1;i=e[i].nxt1)        {            if(dis[e[i].u]>dis[pre.v]+e[i].c)            {                dis[e[i].u]=dis[pre.v]+e[i].c;                que.push(qnode(e[i].u,0));            }        }    }}LL a_star(int src){    priority_queue<qnode> que;    que.push(qnode(src,0));    k--;    while(!que.empty())    {        qnode pre=que.top();que.pop();        if(pre.v==en)        {            if(k) k--;            else return pre.c;        }        for(int i=head[pre.v];i!=-1;i=e[i].nxt)            que.push(qnode(e[i].v,pre.c+e[i].c));    }    return -1;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        memset(head,-1,sizeof(head));        memset(head1,-1,sizeof(head1));        tot=0;        for(int i=0;i<m;i++)        {            int u,v;LL c;            scanf("%d%d%lld",&u,&v,&c);            addedge(u,v,c);            addedge(v,u,c);        }        st=1,en=n;k=2;        dij(en);        if(st==en) k++;        printf("%lld\n",a_star(st));    }    return 0;}

次短路解法:

///求次短路///使用优先队列Dijkstra算法///复杂度O(ElogV)///注意初始化///dist2[v]=min(dist[u]+e(u,v),dist2[u]+e(u,v))#include<iostream>#include<cstdio>#include<vector>#include<cmath>#include<algorithm>#include<map>#include<cstring>#include<string>#include<set>#include<queue>#include<fstream>using namespace std;typedef long long LL;typedef pair<int,int> PII;const int MAXN=1e5+5;const int MAXM=2e5+5;const LL INF=1e18;LL dist[MAXN];int head[MAXN],tot;LL dist2[MAXN];//次短距离int pre[MAXN];struct Edge{    int from,to,nxt;    LL cost;    Edge(){}    Edge(int _from,int _to,LL _cost):from(_from),to(_to),cost(_cost){}}e[MAXM];void addedge(int u,int v,int w){    e[tot].from=u;e[tot].to=v;e[tot].cost=w;    e[tot].nxt=head[u];head[u]=tot++;}struct qnode{    int v;    LL c;    qnode(LL _c=0,int _v=0):c(_c),v(_v){}    bool operator < (const qnode &rhs) const {return c>rhs.c;}};void Dijkstra(int n,int st)//点的编号从1开始{    for(int i=0;i<=n;i++) dist[i]=INF,dist2[i]=INF;    priority_queue<qnode> pq;    while(!pq.empty()) pq.pop();    dist[st]=0;    pq.push(qnode(0,st));    qnode frt;    while(!pq.empty())    {        frt=pq.top(); pq.pop();        int u=frt.v;        LL d=frt.c;        if(dist2[u]<d) continue;        for(int i=head[u];i!=-1;i=e[i].nxt)        {            int to=e[i].to;            LL cost=e[i].cost;            LL d2=d+cost;            if(dist[to]>d2)            {                swap(dist[to],d2);                pre[to]=u;                pq.push(qnode(dist[to],to));            }            if(dist2[to]>d2&&dist[to]<d2)            {                dist2[to]=d2;                pq.push(qnode(dist2[to],to));            }        }    }}int main(){    int T;    int vN,eN;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&vN,&eN);        tot=0;memset(head,-1,sizeof(head));        int u,v,w;        for(int i=1;i<=eN;i++)        {            scanf("%d%d%d",&u,&v,&w);            addedge(u,v,w);addedge(v,u,w);        }        int st,ed;        st=1,ed=vN;        //scanf("%d%d",&st,&ed);        //if(st==ed) {printf("0\n");continue;}        Dijkstra(vN,st);//        for(int i=0;i<=vN-1;i++)//            printf("%d ",dist[i]);//        printf("\n");//        for(int i=0;i<=vN-1;i++)//            printf("%d ",pre[i]);//        printf("\n");        printf("%lld\n",dist2[ed]);    }    return 0;}/*14 61 2 11 2 51 3 22 3 22 4 12 4 6ans:4*/
原创粉丝点击