【提高组】最短路

P1339 [USACO09OCT]热浪Heat Wave

板子题,练习堆优dj。

#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;
}
View Code

 

P1462 通往奥格瑞玛的道路

二分+dj。

#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;
}
View Code

 

P1119 灾后重建

很好地考察算法(Floyd)理解的题目。一轮复习时一定要理解算法+充分刷题。同时也提醒了我要重视数据范围

以为比较难,直接往堆优dj想,没认真考虑数据范围,想当然地以为除了堆优dj一定会炸时间(结果堆优炸了),很快想出了一个写法。

结果:改了半天发现没read( )没初始化dis没判断dis1>dis2+w(多打题,做题时保持精神)->过了样例提交20分,结构体开小了,node记得<<1(还顺手打成了>>)但写成了点而非边->再交T了40分打了个输出优化->50分T了->开了O2T了70分->意识到算法有问题但又懒得想&改了翻题解,哇原来是Floyd。

代码简单又好想。主要难在对Floyd算法的理解与意识到可以用Floyd过。

#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;
} 
View Code

附上Floyd理解好文   https://www.cnblogs.com/GumpYan/p/5540549.html

 

P1522 牛的旅行 Cow Tours

1.计算每个牧场的直径:枚举计算牧场中每个点距离其他点的距离,不连通则初始化为inf(读懂输入中给的矩阵..花了我一会儿)。然后Floyd跑最短路。

2.计算新牧场直径:枚举不联通的点,直径为两个点分别离其他点的最大距离+两个点的距离中的最小值。

3.计算结果:ans=max(每个牧场的直径,新牧场直径)。

难点在读懂题目吧...好绕。

#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;
}
View Code

 

posted @ 2019-10-09 21:46  jian_song  阅读(194)  评论(0编辑  收藏  举报