UESTC 915 -- 方老师的分身 II (spfa,dijkstra)

来源:互联网 发布:流量控制软件电脑 编辑:程序博客网 时间:2024/04/30 04:38

题目大意:求从一个点到另一个点至少经过k条路径的最短路径长度;

思路分析:用两个变量u和e来维护一个点的dis,u表示当前点的编号,e表示经过多少条边,dis[u][e] 表示走到u点经过e条边的最短路径长度,因为是至少是k条边,所以大于k条边的当做是k条边来处理就好了。

代码实现:

SPFA:

#include<cstdio>#include<cstring>#include<queue>#define Min(a,b) ((a)<(b)?(a):(b))using namespace std;const int INF=0x3f3f3f3f;int n,m,S,T,K,top,dis[5005][55];bool vis[5005][55];struct Node{    int v1,va;    Node *next;}*h[5005],e[200005];struct Status{    int v1,k;    Status(int _v1=0,int _k=0):v1(_v1),k(_k){}};void Addedge(int from,int to,int val){    Node *p=&e[top++];    p->v1=to;    p->va=val;    p->next=h[from];    h[from]=p;}void Spfa(){    queue<Status> q;    dis[S][0]=0;    q.push(Status(S,0));    Status head;    int tmp;    while(!q.empty()){        head=q.front();        q.pop();        vis[head.v1][head.k]=0;        for(Node *p=h[head.v1];p;p=p->next){            tmp=head.k+1;            tmp=Min(tmp,K);            if(dis[p->v1][tmp]>dis[head.v1][head.k]+p->va){                dis[p->v1][tmp]=dis[head.v1][head.k]+p->va;                if(!vis[p->v1][tmp]){                    vis[p->v1][tmp]=1;                    q.push(Status(p->v1,tmp));                }            }        }    }}int main(){    while(~scanf("%d%d",&n,&m)){        memset(h,0,sizeof(h));        memset(vis,0,sizeof(vis));        memset(dis,0x3f,sizeof(dis));        top=0;        int a,b,val;        while(m--){            scanf("%d%d%d",&a,&b,&val);            Addedge(a,b,val);            Addedge(b,a,val);        }        scanf("%d%d%d",&S,&T,&K);        Spfa();        int res;        if(dis[T][K]<INF) printf("%d\n",dis[T][K]);        else printf("-1\n");    }}

Dijkstra:注意邻接表用的结构体和优先队列用的结构体一定要分开写,不然内存会超的!!!

#include<cstdio>#include<cstring>#include<queue>#define Min(a,b) ((a)<(b)?(a):(b))using namespace std;const int INF=0x3f3f3f3f;int n,m,S,T,K,top,dis[5005][55];bool vis[5005][55];struct Node{    int v1,va;    Node *next;}*h[5005],e[200005];struct Status{    int v1,va,k;    Status(int _v1=0,int _va=0,int _k=0):v1(_v1),va(_va),k(_k){}    bool operator<(const Status rhs)const{        return va>rhs.va;    }};void Addedge(int from,int to,int val){    Node *p=&e[top++];    p->v1=to;    p->va=val;    p->next=h[from];    h[from]=p;}void Dijkstra(){    priority_queue<Status> q;    //memset(dis[S],0,sizeof(dis[S]));    dis[S][0]=0;    q.push(Status(S,0,0));    Status head;    int tmp;    while(!q.empty()){        head=q.top();        q.pop();        if(head.v1==T&&head.k==K) break;        vis[head.v1][head.k]=1;        for(Node *p=h[head.v1];p;p=p->next){            tmp=head.k+1;            tmp=Min(tmp,K);            if(!vis[p->v1][tmp]&&dis[p->v1][tmp]>dis[head.v1][head.k]+p->va){                dis[p->v1][tmp]=dis[head.v1][head.k]+p->va;                q.push(Status(p->v1,dis[p->v1][tmp],tmp));            }            //else p->k--;        }    }}int main(){    while(~scanf("%d%d",&n,&m)){        memset(h,0,sizeof(h));        memset(vis,0,sizeof(vis));        memset(dis,0x3f,sizeof(dis));        top=0;        int a,b,val;        while(m--){            scanf("%d%d%d",&a,&b,&val);            Addedge(a,b,val);            Addedge(b,a,val);        }        scanf("%d%d%d",&S,&T,&K);        Dijkstra();        int res;        /*for(int i=K;i<50;i++){            if(dis[T][i]<INF){                res=dis[T][i];                flag=1;                break;            }        }*/        //res=Min(dis[T][K],dis[T][K+1]);        /*for(int i=1;i<=n;i++){            printf("%d: ",i);            for(Status *p=h[i];p;p=p->next) printf("%d %d ",p->v1,p->va);            printf("\n");        }        for(int i=1;i<=n;++i){            for(int j=0;j<K+2;j++) printf("%d ",dis[i][j]);            printf("\n");        }*/        if(dis[T][K]<INF) printf("%d\n",dis[T][K]);        else printf("-1\n");    }}


0 0