首页 > 代码库 > BZOJ 1050 HAOI2006 旅行comf 动点SPFA
BZOJ 1050 HAOI2006 旅行comf 动点SPFA
题目大意:给定一个无向图,每条边上有权值,求起点到终点的路径中最长边和最短边的最小比值
随手点开一道居然是动点SPFA的裸题…… 魔法森林都切了这个问题就不大了
我们把边权排序,从大到小加进这个图中,每加进一条边就把边的两个端点加进队列,直接跑SPFA,维护起点到每个点路径上的最长边的最小值,然后用当前边权作为分母更新ans
这样可以保证每次跑出来的都是当前边为最短边时起点到终点的最长边的最小值,同时由于我们保留了上一次的信息而不至于超时
好强大的算法……可惜搞不出来时间复杂度0.0
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 510 using namespace std; struct edge{ int x,y,f; bool operator < (const edge &z) const { return f > z.f; } }edges[5050]; struct abcd{ int to,f,next; }table[10100]; int head[M],tot; int n,m,s,t,a,b; double ans=1e7; int f[M],v[M]; int q[65540]; unsigned short r,h; inline void SPFA() { int i; while(r!=h) { int x=q[++h]; v[x]=0; for(i=head[x];i;i=table[i].next) if(f[table[i].to]>max(f[x],table[i].f)) { f[table[i].to]=max(f[x],table[i].f); if(!v[table[i].to]) v[table[i].to]=1,q[++r]=table[i].to; } } } inline void Add(int x,int y,int z) { table[++tot].to=y; table[tot].f=z; table[tot].next=head[x]; head[x]=tot; } int main() { int i,x,y; cin>>n>>m; for(i=1;i<=m;i++) scanf("%d%d%d",&edges[i].x,&edges[i].y,&edges[i].f); cin>>s>>t; sort(edges+1,edges+m+1); memset(f,0x3f,sizeof f); f[s]=0; for(i=1;i<=m;i++) { x=edges[i].x; y=edges[i].y; Add(x,y,edges[i].f); Add(y,x,edges[i].f); if(f[x]<f[y]) swap(x,y); if(f[x]<=max(f[y],edges[i].f)) continue; f[x]=max(f[y],edges[i].f); q[++r]=x; SPFA(); if((double)f[t]/edges[i].f<ans) ans=(double)f[t]/edges[i].f,a=f[t],b=edges[i].f; } if(ans==1e7) puts("IMPOSSIBLE"); else if(a%b==0) cout<<a/b<<endl; else cout<<a/__gcd(a,b)<<'/'<<b/__gcd(a,b)<<endl; }
BZOJ 1050 HAOI2006 旅行comf 动点SPFA
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。