金华邀请赛B题poj 4046(spfa求最短路)

来源:互联网 发布:zip解压软件下载mac 编辑:程序博客网 时间:2024/05/22 03:28

题目大意:给定一个无向图,边上有权值,顶点也有权值。有q次询问,每次询问两个顶点,求这两个顶点之间(的路加上这条路上的最大的顶点权值)的最小值。

思路:枚举点,然后求该点到a,b的最小距离。spfa的期望复杂度是O(ke),k一般在2左右,然后,就可以在这道题目大显身手了,这题时限非常紧,一般都是几千毫秒过的,时限只给了5000MS。所以,裸的spfa和暴力询问还是会超时。

关键方程:(start为你枚举的点)                  if(val[v]<=val[start]&&dis[v]>dis[top]+edge[i].w)
                                                                        if(dis[u]!=inf&&dis[v]!=inf&&ans[i]>dis[u]+dis[v]+val[start])
                                                                        ans[i]=dis[u]+dis[v]+val[start];

 

 

#include <iostream>#include <cstring>#include <vector>#include <cstdio>#define MAXN 1005#define MAXM 40005#define inf 10000000000007LLusing namespace std;int head[MAXN];int cnt=0;int n,m;long long val[MAXN];int qua[MAXM],qub[MAXM];int q;long long  ans[MAXM];int vis[MAXN];long long  dis[MAXN];int mystack[MAXM*5];struct Node{    int v;    long long w;    int next;}edge[MAXM];void init(){    cnt=0;    memset(head,-1,sizeof(head));}void addedge(int u,int v,long long w){    edge[cnt].v=v;    edge[cnt].w=w;    edge[cnt].next=head[u];    head[u]=cnt++;}void spfa(int start){    for(int i=0;i<=n+3;i++)     vis[i]=0,dis[i]=inf;    vis[start]=1;    dis[start]=0;    int h=0,r=0;    mystack[r++]=start;    while(h<r)    {        int top=mystack[h++];        vis[top]=0;        for(int i=head[top];i!=-1;i=edge[i].next)        {            int v=edge[i].v;            if(val[v]<=val[start]&&dis[v]>dis[top]+edge[i].w)            {              dis[v]=dis[top]+edge[i].w;              if(!vis[v])              {                mystack[r++]=v;                vis[v]=1;              }            }        }    }    for(int i=1;i<=q;i++)    {        int u=qua[i];        int v=qub[i];        if(dis[u]!=inf&&dis[v]!=inf&&ans[i]>dis[u]+dis[v]+val[start])        ans[i]=dis[u]+dis[v]+val[start];    }}int main(){    int u,v;    __int64 w;    while(scanf("%d%d",&n,&m)==2)    {     if(n==0&&m==0)break;        init();     for(int i=1;i<=n;i++)      scanf("%I64d",&val[i]);     for(int i=1;i<=m;i++)     {         scanf("%d%d%I64d",&u,&v,&w);         addedge(u,v,w);         addedge(v,u,w);     }       scanf("%d",&q);      for(int i=1;i<=q;i++)       scanf("%d%d",&qua[i],&qub[i]),ans[i]=inf;      for(int i=1;i<=n;i++)       spfa(i);              for(int i=1;i<=q;i++)       {        if(ans[i]==inf)         printf("-1\n");        else         printf("%I64d\n",ans[i]);       }      puts("");    }    return 0;}

原创粉丝点击