zoukankan      html  css  js  c++  java
  • 算法笔记--最短路算法

    1.单源最短路问题

    ①Bellman-ford算法:

    const int N=1e3+5; 
    const int INF=0x3f3f3f3f;
    struct edge{
        int u,v,cost;
    };
    int d[N];
    int V;
    vector<edge>e;
    void Bellman_ford(int s)
    {
        for(int i=0;i<V;i++)d[i]=INF;
        d[s]=0;
        while(true)
        {
            bool upd=false;
            for(int i=0;i<e.size();i++)
            {
                if(d[e[i].u]!=INF&&d[e[i].v]>d[e[i].u]+e[i].cost)
                {
                    upd=true;
                    d[e[i].v]=d[e[i].u]+e[i].cost;
                }
            }
            if(!upd)break;
        }
    }
    bool find_negative_loop()
    {
        mem(d,0);
        for(int i=0;i<V;i++)
        {
            for(int j=0;j<e.size();j++)
            {
                if(d[e[j].v]>d[e[j].u]+e[j].cost)
                {
                    d[e[j].v]=d[e[j].u]+e[j].cost;
                    if(i==V-1)return true;    
                } 
            }
        }    
        return false;
    }

    例题:poj 1860 Currency Exchange

    思路:判断是否存在正权环。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a)) 
    
    const int N=1e3+5;
    int n,m,s;
    double V;
    struct edge
    {
        int u,v;
        double r,c;
    };
    vector<edge>e;
    double d[N];
    bool Bellman()
    {
        for(int i=0;i<=n;i++)d[i]=0;
        d[s]=V;
        for(int i=1;i<=n;i++)
        {
            bool upd=false;
            for(int j=0;j<e.size();j++)
            {
                if(d[e[j].v]<(d[e[j].u]-e[j].c)*e[j].r)
                {
                    if(i==n)return true;
                    upd=true;
                    d[e[j].v]=(d[e[j].u]-e[j].c)*e[j].r;
                }
            }
            if(!upd)return false;
        }
        return false;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin>>n>>m>>s>>V;
        int u,v;
        double r,c,_r,_c;
        while(m--)
        {
            cin>>u>>v>>r>>c>>_r>>_c;
            e.pb(edge{u,v,r,c});
            e.pb(edge{v,u,_r,_c});
        }
        if(Bellman())cout<<"YES"<<endl;
        else cout<<"NO"<<endl; 
        return 0; 
    }
    View Code

    ②Dijkstra算法:

    普通版:

    const int INF=0x3f3f3f3f;
    const int N=105;
    int g[N][N];
    int d[N];
    bool vis[N];
    int n,m;
    
    void Dijkstra(int s)
    {
        mem(d,INF);
        mem(vis,false);
        d[s]=0;
        
        while(true)
        {
            int v=-1;
            for(int i=1;i<=n;i++)
            if(!vis[i]&&(v==-1||d[i]<d[v]))v=i;
            
            if(v==-1)break;
            vis[v]=true;
            
            for(int i=1;i<=n;i++)
            {
                d[i]=min(d[i],d[v]+g[v][i]);
            }
        }
    }

    例题:hdu2544最短路

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define ls rt<<1,l,m
    #define rs rt<<1|1,m+1,r
    #define pb push_back
    #define mem(a,b) memset((a),(b),sizeof(a))
    const int INF=0x3f3f3f3f;
    const int N=105;
    int g[N][N];
    int d[N];
    bool vis[N];
    int n,m;
    
    void Dijkstra(int s)
    {
        mem(d,INF);
        mem(vis,false);
        d[s]=0;
        
        while(true)
        {
            int v=-1;
            for(int i=1;i<=n;i++)
            if(!vis[i]&&(v==-1||d[i]<d[v]))v=i;
            
            if(v==-1)break;
            vis[v]=true;
            
            for(int i=1;i<=n;i++)
            {
                d[i]=min(d[i],d[v]+g[v][i]);
            }
        }
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m)&&n&&m)
        {
            mem(g,INF);
            for(int i=0;i<m;i++)
            {
                int a,b,c;
                cin>>a>>b>>c;
                g[a][b]=c;
                g[b][a]=c;
            }
            Dijkstra(1);
            printf("%d
    ",d[n]);
        }
        return 0;
    } 
    View Code

     优先队列优化版:

    const int N=1e3+5;
    const int INF=0x3f3f3f3f;
    int d[N];
    int V;
    struct edge{
        int to,cost;
    };
    vector<edge>g[N];
    void dijkstra(int s)
    {
        priority_queue<pii,vector<pii>,greater<pii> >q;
        mem(d,INF);
        d[s]=0;
        q.push(mp(0,s));
        while(!q.empty())
        {
            pii p=q.top();
            q.pop();
            int v=p.second;
            if(d[v]<p.first)continue;
            for(int i=0;i<g[v].size();i++)
            {
                edge e=g[v][i];
                if(d[e.to]>d[v]+e.cost)
                {
                    d[e.to]=d[v]+e.cost;
                    q.push(mp(d[e.to],e.to));
                }
            }
        }
    }

    例题:hdu2544最短路

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pii pair<int,int>
    
    const int N=1e3+5;
    const int INF=0x3f3f3f3f;
    int d[N];
    int V;
    struct edge{
        int to,cost;
    };
    vector<edge>g[N];
    void dijkstra(int s)
    {
        priority_queue<pii,vector<pii>,greater<pii> >q;
        mem(d,INF);
        d[s]=0;
        q.push(mp(0,s));
        while(!q.empty())
        {
            pii p=q.top();
            q.pop();
            int v=p.second;
            if(d[v]<p.first)continue;
            for(int i=0;i<g[v].size();i++)
            {
                edge e=g[v][i];
                if(d[e.to]>d[v]+e.cost)
                {
                    d[e.to]=d[v]+e.cost;
                    q.push(mp(d[e.to],e.to));
                }
            }
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n,m,a,b,c;
        while(cin>>n>>m)
        {
            if(n==0&&m==0)break;
            for(int i=0;i<N;i++)g[i].clear();
            for(int i=0;i<m;i++)
            {
                cin>>a>>b>>c;
                g[a].pb(edge{b,c});
                g[b].pb(edge{a,c});
            }
            dijkstra(1);
            cout<<d[n]<<endl;
        }
        return 0;
    } 
    View Code

     ③spfa算法:

    bool spfa(int s)
    {
        mem(d,INF);
        mem(c,0);
        mem(vis,false);
        d[s]=0;
        c[s]=1;
        vis[s]=true;
        queue<int>q;
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            vis[u]=false;
            for(int i=head[u];~i;i=edge[i].next)
            {
                if(d[edge[i].to]>d[u]+edge[i].w)
                {
                    d[edge[i].to]=d[u]+edge[i].w;
                    if(!vis[edge[i].to])
                    {
                        vis[edge[i].to]=true;
                        c[edge[i].to]++;
                        q.push(edge[i].to);
                        if(c[edge[i].to]>=n)
                        {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    spfa判负环:https://blog.csdn.net/forever_dreams/article/details/81161527

    2.任意两点间的最短路问题

    ①Floyd-Warshall算法

    int d[N][N];
    int n;
    void Floyd()
    {
        for(int k=1;k<=n;k++)
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
            }
        }
    }

    例题:hdu2544最短路

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pii pair<int,int>
    
    const int N=1e3+5;
    const int INF=0x3f3f3f3f;
    int d[N][N];
    int n;
    void Floyd()
    {
        for(int k=1;k<=n;k++)
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
            }
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int m,a,b,c;
        while(cin>>n>>m)
        {
            if(n==0&&m==0)break;
            mem(d,INF);
            for(int i=1;i<=n;i++)d[i][i]=0;
            for(int i=0;i<m;i++)
            {
                cin>>a>>b>>c;
                d[a][b]=c;
                d[b][a]=c;
            }
            Floyd(); 
            cout<<d[1][n]<<endl;
        }
        return 0;
    } 
    View Code

    3.路径还原:

    const int N=1e3+5;
    const int INF=0x3f3f3f3f;
    int d[N];
    int pre[N];
    struct edge
    {
        int to,cost;
    };
    vector<edge>g[N];
    void dijkstra(int s)
    {
        mem(d,INF);
        mem(pre,-1);
        priority_queue<pii,vector<pii>,greater<pii> >q;
        d[s]=0;
        q.push(mp(0,s));
        while(!q.empty())
        {
            pii p=q.top();
            q.pop();
            int v=p.second;
            if(d[v]<p.first)continue; 
            for(int i=0;i<g[v].size();i++)
            {
                edge e=g[v][i];
                if(d[e.to]>d[v]+e.cost)
                {
                    d[e.to]=d[v]+e.cost;
                    pre[e.to]=v;
                    q.push(mp(d[e.to],e.to));
                }
            }
        }
    }
    
    vector<int> get_path(int t)
    {
        vector<int> path;
        for(;t!=-1;t=pre[t])path.pb(t);
        reverse(path.begin(),path.end());
        return path;
    }

     例题:

    POJ 2387

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long 
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=1e3+5;
    const int INF=0x3f3f3f3f;
    struct edge
    {
        int to,cost;
    };
    int d[N];
    vector<edge>g[N];
    
    void dijkstra(int s)
    {
        mem(d,INF);    
        d[s]=0;
        priority_queue<pii,vector<pii>,greater<pii> >q;
        q.push(mp(0,s));
        while(!q.empty())
        {
            pii p=q.top();
            q.pop();
            int v=p.second;
            if(d[v]<p.first)continue;
            for(int i=0;i<g[v].size();i++)
            {
                edge e=g[v][i];
                if(d[e.to]>d[v]+e.cost)
                {
                    d[e.to]=d[v]+e.cost;
                    q.push(mp(d[e.to],e.to));
                }
            }
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int t,n,a,b,c;
        while(cin>>t>>n)
        {
            for(int i=0;i<=n;i++)g[i].clear();
            while(t--)
            {
                cin>>a>>b>>c;
                g[a].pb(edge{b,c});
                g[b].pb(edge{a,c});
            }
            dijkstra(n);
            cout<<d[1]<<endl;
        }
        return 0;
    }
    View Code

    POJ 2253

    路径最大权值最小路

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<iomanip>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define pdi pair<double,int>
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=205;
    const int INF=0x3f3f3f3f;
    struct edge
    {
        int to;
        double cost;
    };
    vector<edge>g[N];
    bool vis[N];
    double d[N];
    double x[N],y[N];
    void dijkstra(int s)
    {
        for(int i=0;i<N;i++)d[i]=INF;
        mem(vis,false);
        d[s]=0;
        priority_queue<pdi,vector<pdi>,greater<pdi> >q;
        q.push(mp(0,s));
        while(!q.empty())
        {
            pii p=q.top();
            q.pop();
            int v=p.second;
            if(vis[v])continue;
            vis[v]=true;
            for(int i=0;i<g[v].size();i++)
            {
                edge e=g[v][i];
                if(d[e.to]>max(d[v],e.cost))
                {
                    d[e.to]=max(d[v],e.cost);
                    q.push(mp(d[e.to],e.to));
                }
            }
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n;
        int cnt=0;
        while(cin>>n&&n)
        {
            for(int i=1;i<=n;i++)
            {
                g[i].clear();
                cin>>x[i]>>y[i];
            }
            for(int i=1;i<=n;i++)
            {
                for(int j=i+1;j<=n;j++)
                {
                    double dis=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
                    g[i].pb(edge{j,dis});
                    g[j].pb(edge{i,dis});
                }
            }
            dijkstra(1);
            cout<<"Scenario #"<<++cnt<<endl;
            cout<<"Frog Distance = "<<fixed<<setprecision(3)<<d[2]<<endl;
            cout<<endl;
        }
        return 0;
    } 
    View Code

     POJ 1797

    路径流量(最小权值)最大路

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<iomanip>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define pdi pair<double,int>
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=1e3+5;
    const int INF=0x3f3f3f3f;
    struct edge
    {
        int to,cost;
    };
    vector<edge>g[N];
    int d[N];
    bool vis[N];
    void dijkstra(int s)
    {
        mem(vis,false);
        mem(d,0);
        priority_queue<pii>q;
        vis[s]=true;
        for(int i=0;i<g[1].size();i++)
        {
            edge e=g[1][i]; 
            d[e.to]=e.cost;
            q.push(mp(e.cost,e.to));
        }
        while(!q.empty())
        {
            pii p=q.top();
            q.pop();
            int v=p.second;
            if(vis[v])continue;
            vis[v]=true;
            for(int i=0;i<g[v].size();i++)
            {
                edge e=g[v][i];
                if(d[e.to]<min(d[v],e.cost))
                {
                    d[e.to]=min(d[v],e.cost);
                    q.push(mp(d[e.to],e.to));
                }
            }
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int T,n,m,u,v,cost;
        cin>>T;
        for(int i=1;i<=T;i++)
        {
            cin>>n>>m;
            for(int i=0;i<=n;i++)g[i].clear();
            while(m--)
            {
                cin>>u>>v>>cost;
                g[u].pb(edge{v,cost});
                g[v].pb(edge{u,cost}); 
            }
            dijkstra(1);
            cout<<"Scenario #"<<i<<":"<<endl<<d[n]<<endl<<endl;
        }
        return 0;
    }
    View Code

     POJ - 3259

    判负环

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<iomanip>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define pdi pair<double,int>
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=555;
    int d[N];
    int n;
    struct edge
    {
        int u,v,cost;
    };
    vector<edge>e;
    bool Bellman(int s)
    {
        mem(d,0);
        for(int i=1;i<=n;i++)
        {
            bool upd=false;
            for(int j=0;j<e.size();j++)
            {
                if(d[e[j].v]>d[e[j].u]+e[j].cost)
                {
                    if(i==n)return true;
                    d[e[j].v]=d[e[j].u]+e[j].cost;
                    upd=true;
                }
            }
            if(!upd)return false;
        }
        return false;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int f,u,v,t,m,w;
        cin>>f;
        while(f--)
        {
            cin>>n>>m>>w;
            e.clear();
            while(m--)
            {
                cin>>u>>v>>t;
                e.pb(edge{u,v,t});
                e.pb(edge{v,u,t});
            }
            while(w--)
            {
                cin>>u>>v>>t;
                e.pb(edge{u,v,-t});
            } 
            if(Bellman(1))cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
        return 0;
    }
    View Code

    POJ - 3660

    传递闭包

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=105;
    bool Mp[N][N];
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n,m,u,v;
        cin>>n>>m;
        mem(Mp,false);
        for(int i=0;i<m;i++)cin>>u>>v,Mp[u][v]=true;
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    Mp[i][j]=max(Mp[i][j],Mp[i][k]&&Mp[k][j]);
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            int t=0;
            for(int j=1;j<=n;j++)t+=Mp[i][j]+Mp[j][i];
            if(t==n-1)cnt++;
        }
        cout<<cnt<<endl;
        return 0;
    }
    View Code

     POJ - 1502

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=105;
    const int INF=0x3f3f3f3f;
    int head[N];
    ll d[N];
    int cnt;
    struct edge
    {
        int to,w,next;
    }edge[N*N];
    void add_edge(int u,int v,int w)
    {
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    void dijkstra(int s)
    {
        mem(d,INF);
        priority_queue<pii,vector<pii>,greater<pii> >q;
        d[s]=0;
        q.push(mp(0,s));
        while(!q.empty())
        {
            pii p=q.top();
            q.pop();
            int u=p.second;
            if(d[u]<p.first)continue;
            for(int i=head[u];~i;i=edge[i].next)
            {
                if(d[edge[i].to]>d[u]+edge[i].w)
                {
                    d[edge[i].to]=d[u]+edge[i].w;
                    q.push(mp(d[edge[i].to],edge[i].to));
                }
            }
    
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n;
        string w;
        cin>>n;
        cnt=0;
        mem(head,-1);
        for(int i=2;i<=n;i++)
        {
            for(int j=1;j<i;j++)
            {
                cin>>w;
                int cost=0;
                if(w=="x")cost=INF;
                else
                {for(int i=0;i<w.size();i++)cost=cost*10+w[i]-'0';}
                add_edge(i,j,cost);
                add_edge(j,i,cost);
            }
        }
        //cout<<1<<endl;
        dijkstra(1);
        ll mx=0;
        for(int i=1;i<=n;i++)mx=max(mx,d[i]);
        cout<<mx<<endl;
        return 0;
    }
    View Code
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=105;
    const int INF=0x3f3f3f3f;
    int Mp[N][N];
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n;
        string w;
        cin>>n;
        for(int i=2;i<=n;i++)
        {
            for(int j=1;j<i;j++)
            {
                cin>>w;
                int cost=0;
                if(w=="x")cost=INF;
                else
                {for(int i=0;i<w.size();i++)cost=cost*10+w[i]-'0';}
                Mp[i][j]=cost;
                Mp[j][i]=cost;
            }
        }
        int mx=0;
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    Mp[i][j]=min(Mp[i][k]+Mp[k][j],Mp[i][j]);
        for(int i=2;i<=n;i++)mx=max(mx,Mp[1][i]);
        cout<<mx<<endl;
        return 0;
    }
    View Code

    POJ 2240

    判断是否存在正权环,bellman有点慢,好像spfa快一点

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=50;
    struct edge
    {
        int u,v;
        double w;
    };
    double d[N];
    int n;
    vector<edge>e;
    map<string,int>mp;
    bool Bellman()
    {
        for(int i=1;i<=n;i++)d[i]=0;
        d[1]=1;
        for(int i=1;i<=n;i++)
        {
            bool upd=false;
            for(int j=0;j<e.size();j++)
            {
                if(d[e[j].v]<d[e[j].u]*e[j].w)
                {
                    if(i==n)return true;
                    upd=true;
                    d[e[j].v]=d[e[j].u]*e[j].w;
                }
            }
            if(!upd)return false;
        }
        return false;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        string s,t;
        int m;
        double w;
        int cnt=0;
        while(cin>>n&&n)
        {
            mp.clear();
            e.clear();
            for(int i=1;i<=n;i++)cin>>s,mp[s]=i;
            cin>>m;
            for(int i=1;i<=m;i++)
            {
                cin>>s>>w>>t;
                e.pb(edge{mp[s],mp[t],w});
            }
            if(Bellman())cout<<"Case "<<++cnt<<": Yes"<<endl;
            else cout<<"Case "<<++cnt<<": No"<<endl;
        }
        return 0;
    }
    View Code

     POJ 1511

    又做到一题关闭同步失败的,一直TLE,哭唧唧/(ㄒoㄒ)/~~

    求每个点到1的最短路,把图反向,求1的最短路就可以了

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=1e6+5;
    const int INF=0x3f3f3f3f;
    int d[N];
    int head[N];
    int u[N],v[N],w[N];
    int cnt,p;
    struct edge
    {
        int to,w,next;
    }edge[N];
    void add_edge(int u,int v,int w)
    {
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    void dijkstra(int s)
    {
        priority_queue<pii,vector<pii>,greater<pii> >q;
        for(int i=1;i<=p;i++)d[i]=INF;
        d[s]=0;
        q.push(mp(0,s));
        while(!q.empty())
        {
            pii p=q.top();
            q.pop();
            int u=p.second;
            if(d[u]<p.first)continue;
            for(int i=head[u];~i;i=edge[i].next)
            {
                if(d[edge[i].to]>p.first+edge[i].w)
                {
                    d[edge[i].to]=p.first+edge[i].w;
                    q.push(mp(d[edge[i].to],edge[i].to));
                }
            }
        }
    }
    int main()
    {
        int T,q;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&p,&q);
            cnt=0;
            for(int i=1;i<=p;i++)head[i]=-1;
            for(int i=1;i<=q;i++)
            {
                scanf("%d%d%d",&u[i],&v[i],&w[i]);
                add_edge(u[i],v[i],w[i]);
            }
            ll ans=0;
            dijkstra(1);
            for(int i=2;i<=p;i++)ans+=d[i];
            cnt=0;
            for(int i=1;i<=p;i++)head[i]=-1;
            for(int i=1;i<=q;i++)
            add_edge(v[i],u[i],w[i]);
            dijkstra(1);
            for(int i=2;i<=p;i++)ans+=d[i];
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code

     POJ 2502

    建好边,跑一遍最短路

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define pii pair<int,int>
    #define pdi pair<double,int>
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=205;
    const int INF=0x3f3f3f3f;
    struct node
    {
        double x,y;
    }a[N];
    double mp[N][N];
    double d[N];
    int cnt;
    void dijkstra(int s)
    {
        priority_queue<pdi,vector<pdi>,greater<pdi> >q;
        for(int i=0;i<cnt;i++)d[i]=INF;
        d[s]=0;
        q.push(pdi(0,s));
        while(!q.empty())
        {
            pdi p=q.top();
            q.pop();
            if(d[p.second]<p.first)continue;
            for(int i=0;i<cnt;i++)
            {
                if(d[i]>d[p.second]+mp[p.second][i])
                {
                    d[i]=d[p.second]+mp[p.second][i];
                    q.push(pdi(d[i],i));
                }
            }
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        double sx,sy,ex,ey;
        double x,y;
        //freopen("in.txt","r",stdin);
        cin>>sx>>sy>>ex>>ey;
        double prex=-1;
        double prey=-1;
        cnt=0;
        a[cnt].x=sx,a[cnt++].y=sy;
        while(cin>>x>>y)
        {
            if(x!=-1)a[cnt].x=x,a[cnt].y=y;
            if(prex!=-1&&x!=-1)
            {
                double t=sqrt((a[cnt].x-a[cnt-1].x)*(a[cnt].x-a[cnt-1].x)+(a[cnt].y-a[cnt-1].y)*(a[cnt].y-a[cnt-1].y))/40000;
                mp[cnt][cnt-1]=t;
                mp[cnt-1][cnt]=t;
            }
            if(x!=-1)cnt++;
            prex=x;
            prey=y;
        }
        a[cnt].x=ex;
        a[cnt++].y=ey;
        for(int i=0;i<cnt;i++)
        {
            for(int j=0;j<cnt;j++)
            {
                if(mp[i][j]>0)mp[i][j]=min(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))/10000,mp[i][j]);
                else mp[i][j]=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))/10000;
            }
        }
        dijkstra(0);
        cout<<(int)(d[cnt-1]*60+0.5)<<endl;
        //fclose(stdin);
        return 0;
    }
    View Code

     POJ 3159

    枚举能跑的点上下界

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define pdi pair<double,int>
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=105;
    const int INF=0x3f3f3f3f;
    int n,m;
    struct edge
    {
        int to,w,next;
    }edge[N*N];
    int head[N];
    int level[N];
    int d[N];
    int x[N];
    int v[N][N];
    int t[N][N];
    int p[N];
    int cnt=0;
    void add_edge(int u,int v,int w)
    {
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    void dijkstra(int s,int l,int r)
    {
        priority_queue<pii,vector<pii>,greater<pii> >q;
        mem(d,INF);
        d[s]=0;
        q.push(mp(0,s));
        while(!q.empty())
        {
            pii p=q.top();
            q.pop();
            if(d[p.second]<p.first)continue;
            for(int i=head[p.second];~i;i=edge[i].next)
            {
                if(l<=level[edge[i].to]&&level[edge[i].to]<=r&&d[edge[i].to]>d[p.second]+edge[i].w)
                {
                    d[edge[i].to]=d[p.second]+edge[i].w;
                    q.push(mp(d[edge[i].to],edge[i].to));
                }
            }
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin>>m>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>p[i]>>level[i]>>x[i];
            for(int j=0;j<x[i];j++)
            {
                cin>>t[i][j]>>v[i][j];
            }
        }
        mem(head,-1);
        cnt=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<x[i];j++)
            {
                    add_edge(i,t[i][j],v[i][j]);
            }
        }
        int ans=p[1];
        for(int l=level[1]-m;l<=level[1];l++)
        {
            dijkstra(1,l,l+m);
            for(int i=2;i<=n;i++)ans=min(ans,d[i]+p[i]);
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code

     POJ 1847

    水水的一道最短路,把转动次数看成路径权值

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define pdi pair<double,int>
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=105;
    const int INF=0x3f3f3f3f;
    int head[N];
    int d[N];
    int cnt;
    struct edge
    {
        int to,w,next;
    }edge[N*N];
    void add_edge(int u,int v,int w)
    {
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    void dijkstra(int s)
    {
        priority_queue<pii,vector<pii>,greater<pii> >q;
        mem(d,INF);
        d[s]=0;
        q.push(mp(0,s));
        while(!q.empty())
        {
            pii p=q.top();
            q.pop();
            if(d[p.second]<p.first)continue;
            for(int i=head[p.second];~i;i=edge[i].next)
            {
                if(d[edge[i].to]>d[p.second]+edge[i].w)
                {
                    d[edge[i].to]=d[p.second]+edge[i].w;
                    q.push(mp(d[edge[i].to],edge[i].to));
                }
            }
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n,a,b,t,m;
        cin>>n>>a>>b;
        cnt=0;
        mem(head,-1);
        for(int i=1;i<=n;i++)
        {
            cin>>m;
            if(m)
            {
                m--;
                cin>>t;
                add_edge(i,t,0);
            }
            while(m--)
            {
                cin>>t;
                add_edge(i,t,1);
            }
        }
        dijkstra(a);
        if(d[b]!=INF)cout<<d[b]<<endl;
        else cout<<-1<<endl;
        return 0;
    }
    View Code

     LightOJ 1074

    不会spfa,看来要去学了,用dijkstra剪了一下枝,水过数据

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define pdi pair<double,int>
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=205;
    const int INF=0x3f3f3f3f;
    int d[N];
    int a[N];
    int head[N];
    int cnt,n;
    struct edge
    {
        int to,w,next;
    }edge[N*N];
    void add_edge(int u,int v,int w)
    {
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    void dijkstra(int s)
    {
        priority_queue<pii,vector<pii>,greater<pii> >q;
        mem(d,INF);
        d[s]=0;
        q.push(mp(0,s));
        while(!q.empty())
        {
            pii p=q.top();
            q.pop();
            if(d[p.second]<p.first)continue;
            for(int i=head[p.second];~i;i=edge[i].next)
            {
                if(d[edge[i].to]>d[p.second]+edge[i].w)
                {
                    d[edge[i].to]=d[p.second]+edge[i].w;
                    if(d[edge[i].to]>-10000)q.push(mp(d[edge[i].to],edge[i].to));
                }
            }
        }
    }
    bool bellman()
    {
        mem(d,0);
        for(int i=1;i<=n;i++)
        {
            bool upd=false;
            for(int j=0;j<cnt;j++)
            {
    
            }
            if(!upd)return false;
        }
        return false;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int T,m,q,cs=0,u,v,t;
        cin>>T;
        while(T--)
        {
            cin>>n;
            for(int i=1;i<=n;i++)cin>>a[i];
            cnt=0;
            mem(head,-1);
            cin>>m;
            while(m--)cin>>u>>v,add_edge(u,v,pow(a[v]-a[u],3));
            dijkstra(1);
            cout<<"Case "<<++cs<<":"<<endl;
            cin>>q;
            while(q--)
            {
                cin>>t;
                if(d[t]!=INF&&d[t]>=3)cout<<d[t]<<endl;
                else cout<<"?"<<endl;
            }
        }
        return 0;
    }
    View Code

    HDU 4725

    没有点的楼层之间不能建边,而且只能将同一层的点和所在楼层连单向边,不然同一层的点之间可以免费跑,wa到死

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define pdi pair<double,int>
    #define pli pair<ll,int>
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=1e5+5;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    int head[2*N];
    bool vis[N];
    ll d[2*N];
    int l[N];
    int cnt;
    int n,c;
    struct edge
    {
        int to,w,next;
    }edge[10*N];
    void add_edge(int u,int v,int w)
    {
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    void dijkstra(int s)
    {
        priority_queue<pli,vector<pli>,greater<pli> >q;
        mem(d,INF);
        d[s]=0;
        q.push(mp(0,s));
        while(!q.empty())
        {
            pli p=q.top();
            q.pop();
            if(d[p.second]<p.first)continue;
            for(int i=head[p.second];~i;i=edge[i].next)
            {
                if(d[edge[i].to]>d[p.second]+edge[i].w)
                {
                    d[edge[i].to]=d[p.second]+edge[i].w;
                    q.push(mp(d[edge[i].to],edge[i].to));
                }
            }
        }
    }
    int main()
    {
        int T,m,t,u,v,w,cs=0;
        scanf("%d",&T);
        while(T--)
        {
            cnt=0;
            mem(head,-1);
            mem(vis,false);
            scanf("%d%d%d",&n,&m,&c);
            for(int i=1;i<=n;i++)scanf("%d",&l[i]),vis[l[i]]=true;
            while(m--)scanf("%d%d%d",&u,&v,&w),add_edge(u,v,w),add_edge(v,u,w);
            for(int i=1;i<n;i++)if(vis[i]&&vis[i+1])add_edge(n+i,n+i+1,c),add_edge(n+i+1,n+i,c);
            for(int i=1;i<=n;i++)
            {
                add_edge(i,l[i]+n,0);
                if(l[i]>1)add_edge(i,l[i]-1+n,c),add_edge(l[i]-1+n,i,c);
                if(l[i]<n)add_edge(i,l[i]+1+n,c),add_edge(l[i]+1+n,i,c);
            }
            dijkstra(1);
            printf("Case #%d: ",++cs);
            if(d[n]!=INF)printf("%lld
    ",d[n]);
            else printf("-1
    ");
        }
        return 0;
    }
    View Code

     POJ 3169

    原来spfa这么简单

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=1e3+5;
    const int INF=0x3f3f3f3f;
    int d[N];
    int head[N];
    bool vis[N];
    int c[N];
    int n;
    int cnt;
    struct edge
    {
        int to,w,next;
    }edge[N*N];
    void add_edge(int u,int v,int w)
    {
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    bool spfa(int s)
    {
        mem(d,INF);
        mem(c,0);
        mem(vis,false);
        d[s]=0;
        c[s]=1;
        vis[s]=true;
        queue<int>q;
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            vis[u]=false;
            for(int i=head[u];~i;i=edge[i].next)
            {
                if(d[edge[i].to]>d[u]+edge[i].w)
                {
                    d[edge[i].to]=d[u]+edge[i].w;
                    if(!vis[edge[i].to])
                    {
                        vis[edge[i].to]=true;
                        c[edge[i].to]++;
                        q.push(edge[i].to);
                        if(c[edge[i].to]>=n)
                        {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int L,D,a,b,c;
        cin>>n>>L>>D;
        mem(head,-1);
        cnt=0;
        while(L--)
        {
            cin>>a>>b>>c;
            add_edge(a,b,c);
        }
        while(D--)
        {
            cin>>a>>b>>c;
            add_edge(b,a,-c);
        }
        if(spfa(1))cout<<-1<<endl;
        else
        {
            if(d[n]==INF)cout<<-2<<endl;
            else cout<<d[n]<<endl;
        }
        return 0;
    }
    View Code

     HDU 4370

    两种情况,一种最短路,一种是从1和n分别出发的环(不包括自环)

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    const int N=305;
    const int INF=0x3f3f3f;
    int cost[N][N];
    int d[N];
    int c[N];
    bool vis[N];
    int n;
    bool spfa(int s)
    {
        mem(vis,false);
        mem(c,0);
        mem(d,0);
        queue<int>q;
        for(int i=1;i<=n;i++)
        {
            if(i==s)d[s]=INF,vis[s]=false;
            else d[i]=cost[s][i],q.push(i),vis[i]=true,c[i]=1;
        }
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            vis[u]=false;
            for(int i=1;i<=n;i++)
            {
                if(d[i]>d[u]+cost[u][i])
                {
                    d[i]=d[u]+cost[u][i];
                    if(!vis[i])
                    {
                        vis[i]=true;
                        q.push(i);
                        c[i]++;
                        if(c[i]>=n)return true;
                    }
                }
            }
        }
        return false;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        while(cin>>n)
        {
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    cin>>cost[i][j];
            spfa(1);
            int ans=d[n];
            int loop1=d[1];
            spfa(n);
            int loop2=d[n];
            cout<<min(ans,loop1+loop2)<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Java实现 LeetCode 242 有效的字母异位词
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 344 反转字符串
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
  • 原文地址:https://www.cnblogs.com/widsom/p/7295449.html
Copyright © 2011-2022 走看看