bzoj 1050 & bzoj 3669 spfa动态加点
两个状态量,有点像控制变量法,单调枚举一个量,spfa维护另一量。
/************************* bzoj 1050 Status: Accepted spfa动态加点 (正解是枚举最小点+并查集,表示还是不会写并查集) 2015-0925 *************************/ #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <queue> using namespace std; const int maxn=500+10; const int maxm=5000*2+10; const int INF=10000000; struct Edge{ int to,next,speed; }; Edge e[maxm]; int head[maxn],etot=0; struct AEdge{ int u,v,speed; bool operator < (const AEdge &x)const{ return speed>x.speed; } }; AEdge aE[maxm]; void addEdge(int u,int v,int speed,int ex){ if(ex==1){ aE[etot/2].u=u; aE[etot/2].v=v; aE[etot/2].speed=speed; } e[etot].speed=speed; e[etot].to=v; e[etot].next=head[u]; head[u]=etot++; } // int n,m,s,t; void read_in(){ memset(head,-1,sizeof(head)); cin>>n>>m; for(int i=1;i<=m;i++){ int x,y,speed; cin>>x>>y>>speed; addEdge(x,y,speed,1); addEdge(y,x,speed,0); } cin>>s>>t; sort(aE,aE+etot/2); } queue<int>q; bool in_queue[maxn]; int d[maxn]; void spfa(int current_speed){ while(!q.empty()){ int u=q.front();q.pop(); for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].to,speed=e[i].speed; if(speed<current_speed)continue; int tmp=max(d[u],speed); if(tmp<d[v]){ d[v]=tmp; if(!in_queue[v]){ in_queue[v]=true; q.push(v); } } } in_queue[u]=false; } } int gcd(int x,int y){ if(y==0)return x; return gcd(y,x%y); } void solve(){ double ans=INF; int ans1,ans2; memset(in_queue,0,sizeof(in_queue)); for(int i=1;i<=n;i++)d[i]=INF; d[s]=0; // int i=0,current_speed=0; while(i<etot/2){ current_speed=aE[i].speed; while(aE[i].speed==current_speed){ int u=aE[i].u,v=aE[i].v; if(d[u]<INF&&!in_queue[u]){in_queue[u]=true; q.push(u);} if(d[v]<INF&&!in_queue[v]){in_queue[v]=true; q.push(v);} i++; } spfa(current_speed); if(d[t]<INF&&double(d[t])/double(current_speed)<ans){ ans=double(d[t])/double(current_speed); ans1=d[t]; ans2=current_speed; } } // if(ans>=INF)cout<<"IMPOSSIBLE"<<endl; else { if(ans1%ans2==0)cout<<ans1/ans2<<endl; else { int c=gcd(ans1,ans2); cout<<ans1/c<<'/'<<ans2/c<<endl; } } } int main(){ read_in(); solve(); return 0; }
/********************* bzoj 3669 Status: Accepted spfa动态加点 (正解是LCT,表示现在不会) 2015-09-25 *********************/ #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <queue> using namespace std; const int maxn=50000+100; const int maxm=100000*2+100; const int INF=1000000; struct Edge{ int to,next,wa,wb; }; Edge e[maxm]; int head[maxn],etot=0; struct AEdge{ int u,v,wa,wb,idx; AEdge(int u,int v,int wa,int wb,int idx):u(u),v(v),wa(wa),wb(wb),idx(idx){} AEdge(){} bool operator < (const AEdge &x)const{ return wa<x.wa; } }; AEdge aE[maxm]; void addEdge(int u,int v,int wa,int wb,int ex){ if(ex==1){ AEdge tmp(u,v,wa,wb,etot); aE[etot/2]=tmp; } e[etot].wa=wa; e[etot].wb=wb; e[etot].to=v; e[etot].next=head[u]; head[u]=etot++; } // int n,m; void read_in(){ memset(head,-1,sizeof(head)); cin>>n>>m; for(int i=1;i<=m;i++){ int x,y,a,b; scanf("%d%d%d%d",&x,&y,&a,&b); addEdge(x,y,a,b,1); addEdge(y,x,a,b,0); } sort(aE,aE+etot/2); } // int d[maxn]; int in_queue[maxn]; // queue<int>q; void spfa(int current_wa){ while(!q.empty()){ int u=q.front();q.pop(); for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].to,wa=e[i].wa,wb=e[i].wb; if(wa>current_wa)continue; int tmp=max(d[u],wb); // //cout<<"Can this v change? "<<u<<' '<<v<<endl; if(tmp<d[v]){ // //cout<<"Yes it can"<<endl; d[v]=tmp; if(!in_queue[v]){ // //cout<<"Even not in queue"<<endl; q.push(v); in_queue[v]=true; } } } in_queue[u]=false; } } // void solve(){ memset(in_queue,0,sizeof(in_queue)); for(int i=1;i<=n;i++){ d[i]=INF; } d[1]=0; // int ans=INF; int i=0,current_wa=0; while(i<etot/2){ current_wa=aE[i].wa; while(aE[i].wa==current_wa){ int u=aE[i].u,v=aE[i].v; if(d[u]<INF&&!in_queue[u]){in_queue[u]=true; q.push(u);} if(d[v]<INF&&!in_queue[v]){in_queue[v]=true; q.push(v);} i++; } spfa(current_wa); ans=min(ans,current_wa+d[n]); } if(d[n]>=INF)cout<<-1<<endl; else cout<<ans<<endl; } int main(){ read_in(); solve(); return 0; }
当有那么一天,你相信你可以做到的时候,那你就真的能够做到!
路在脚下