【提高组】最短路
P1339 [USACO09OCT]热浪Heat Wave
板子题,练习堆优dj。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define For(i,l,r) for(int i=l;i<=r;i++) using namespace std; const int M=6206*2; int n,m,s,f,head[M],tot,dis[M]; bool vis[M]; typedef pair<int,int> PII; priority_queue<PII,vector<PII>,greater<PII> > Q; struct node{ int nxt,to,v; }e[M]; inline void add(int u,int v,int w){ e[++tot].to=v; e[tot].nxt=head[u]; e[tot].v=w; head[u]=tot; } int main(){ scanf("%d%d%d%d",&n,&m,&s,&f); For(i,1,m){ int x,y,z; scanf("%d%d%d",&x,&y,&z); add(x,y,z);add(y,x,z); } memset(dis,0x3f3f3f,sizeof(dis)); dis[s]=0;Q.push(make_pair(0,s)); while(!Q.empty()){ int x=Q.top().second;Q.pop(); if(vis[x]) continue; vis[x]=1; for(int i=head[x];i;i=e[i].nxt){ int to=e[i].to; if(dis[to]>dis[x]+e[i].v){ dis[to]=dis[x]+e[i].v; Q.push(make_pair(dis[to],to)); } } } printf("%d",dis[f]); return 0; }
P1462 通往奥格瑞玛的道路
二分+dj。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<cstring> #include<queue> using namespace std; const int maxn=10010; struct pp { int u; int v; int w; int nex; }e[maxn*maxn]; struct node { int dis; int pos; bool operator <(const node &x) const { return x.dis<dis; } }; int dis[maxn],head[maxn],vis[maxn],cost[maxn],f[maxn]; int n,m,b,s,ans,cnt,res,flag,maxl,l,r; priority_queue <node> q; void add(int x,int y,int z) { e[++cnt].u=x; e[cnt].v=y; e[cnt].w=z; e[cnt].nex=head[x]; head[x]=cnt; } bool go( int t) { for(int i=1;i<=n;i++) dis[i]=1000000010,vis[i]=0; dis[1]=0; q.push((node) {0,1}); //for(int i=1;i<=n;i++) //if(cost[i]>t) vis[i]=1; //else vis[i]=0; while(!q.empty()) { node tmp=q.top(); q.pop(); int x=tmp.pos; if(vis[x]) continue; vis[x]=1; for(int i=head[x];i;i=e[i].nex) { int y=e[i].v; if(dis[y]>dis[x]+e[i].w&&cost[y]<=t) { dis[y]=dis[x]+e[i].w; if(!vis[y]) q.push((node) {dis[y],y} ); } } } if(dis[n]<b) return true; else return false; } int main() { scanf("%d%d%d",&n,&m,&b); for(int i=1;i<=n;i++) scanf("%d",&f[i]),cost[i]=f[i]; sort(f+1,f+1+n); for(int i=1;i<=m;i++) { int aa,bb,cc; scanf("%d%d%d",&aa,&bb,&cc); add(aa,bb,cc);add(bb,aa,cc); } l=1;r=n; if(!go(f[n]+8)) { printf("AFK"); return 0; } while (l<=r) { int mid=(l+r)>>1; if(go(f[mid])) ans=f[mid],r=mid-1; else l=mid+1; } printf("%d",ans); return 0; }
P1119 灾后重建
很好地考察算法(Floyd)理解的题目。一轮复习时一定要理解算法+充分刷题。同时也提醒了我要重视数据范围。
以为比较难,直接往堆优dj想,没认真考虑数据范围,想当然地以为除了堆优dj一定会炸时间(结果堆优炸了),很快想出了一个写法。
结果:改了半天发现没read( )没初始化dis没判断dis1>dis2+w(多打题,做题时保持精神)->过了样例提交20分,结构体开小了,node记得<<1(还顺手打成了>>)但写成了点而非边->再交T了40分打了个输出优化->50分T了->开了O2T了70分->意识到算法有问题但又懒得想&改了翻题解,哇原来是Floyd。
代码简单又好想。主要难在对Floyd算法的理解与意识到可以用Floyd过。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; const int M=205; int n,m,a[M],f[M][M]; inline void updata(int k){ for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(f[i][j]>f[i][k]+f[j][k]) f[i][j]=f[j][i]=f[i][k]+f[k][j]; } } return; } int main(){ cin>>n>>m; for(int i=0;i<n;i++) scanf("%d",a+i); for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ f[i][j]=0x3f3f3f3f; } f[i][i]=0; } int s1,s2,s3; for(int i=1;i<=m;i++){ scanf("%d%d%d",&s1,&s2,&s3); f[s1][s2]=f[s2][s1]=s3; } int q,now=0; cin>>q; for(int i=1;i<=q;i++){ scanf("%d%d%d",&s1,&s2,&s3); while(a[now]<=s3&&now<n){ updata(now);now++; } if(a[s1]>s3||a[s2]>s3) cout<<-1<<endl; else{ if(f[s1][s2]==0x3f3f3f3f) cout<<-1<<endl; else cout<<f[s1][s2]<<endl; } } return 0; }
附上Floyd理解好文 https://www.cnblogs.com/GumpYan/p/5540549.html
P1522 牛的旅行 Cow Tours
1.计算每个牧场的直径:枚举计算牧场中每个点距离其他点的距离,不连通则初始化为inf(读懂输入中给的矩阵..花了我一会儿)。然后Floyd跑最短路。
2.计算新牧场直径:枚举不联通的点,直径为两个点分别离其他点的最大距离+两个点的距离中的最小值。
3.计算结果:ans=max(每个牧场的直径,新牧场直径)。
难点在读懂题目吧...好绕。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define For(i,l,r) for(int i=l;i<=r;i++) using namespace std; const int M=155,inf=0x3f3f3f3f; int n,tmp; double dis[M][M],l[M],l1,l2=inf,ans; struct node{ int x,y; }a[M]; double cal(int i,int j){return sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));} int main(){ scanf("%d",&n); For(i,1,n) scanf("%d%d",&a[i].x,&a[i].y); For(i,1,n) For(j,1,n){ scanf("%1d",&tmp); if(tmp) dis[i][j]=cal(i,j); else if(i!=j)dis[i][j]=inf; } For(k,1,n) For(i,1,n) For(j,1,n) if(dis[i][j]>dis[i][k]+dis[k][j]) dis[i][j]=dis[i][k]+dis[k][j]; For(i,1,n) For(j,1,n){ if(dis[i][j]!=inf) l[i]=max(l[i],dis[i][j]); l1=max(l1,l[i]); } For(i,1,n){ For(j,1,n){ if(dis[i][j]==inf){ l2=min(l[i]+l[j]+cal(i,j),l2); } } } ans=max(l1,l2); printf("%.6f",ans); return 0; }