算法笔记--最短路算法

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\n",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\n",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\n",d[n]);
        else printf("-1\n");
    }
    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

 

posted @ 2017-08-06 17:43  Wisdom+.+  阅读(218)  评论(0编辑  收藏  举报