最短路复习

租用游艇
典型的Dijkstra,套套模板

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstdlib>
#include<string>
#include<vector>
#include<list>
#include<map>
#include<set>
#define fi first
#define se second
#define pb push_back
#define me(a,b) memset(a,b,sizeof(a))
#define INIT() std::ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>P;
const int MAX_N=200+5;
const int INF=0x7fffffff;
const int inf=1000000;
const double EPS=1e-6;
const ull base=123;
const ll mod=1e9+7;
const double pi=4*atan(1.0);
int eg[MAX_N][MAX_N];
int d[MAX_N];
int used[MAX_N];
int main()
{
   
    int n;
    scanf("%d",&n);
    int i;
    for(i=1; i<n; i++)
    {
   
        int j;
        for(j=i+1; j<=n; j++)
        {
   
            scanf("%d",&eg[i][j]);
            eg[j][i]=inf;
        }
    }
    fill(d,d+MAX_N,inf);
    d[1]=0;
    while(1)
    {
   
        int v=-1;
        for(i=1; i<=n; i++)
        {
   
            if(used[i]==0&&(v==-1||d[i]<d[v]))
            {
   
                v=i;
            }
        }
        if(v==-1)
            break;
        used[v]=1;
        for(i=1; i<=n; i++)
        {
   
            if(i==v)
                continue;

            if(eg[v][i]+d[v]<d[i])
            {
   
                d[i]=d[v]+eg[v][i];
            }

        }
    }
    cout<<d[n]<<endl;
}

ob Hunt S
要赚更多的钱,可以换个思路,把赚的钱取相反数,用出去的钱当正数,作为边的权值,那么求出最短路的值,最后取相反数即可。这题理论上是存在负环的,所以必然要用Bellman-Ford或者SPFA(优化)

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstdlib>
#include<string>
#include<vector>
#include<list>
#include<map>
#include<set>
#define fi first
#define se second
#define pb push_back
#define me(a,b) memset(a,b,sizeof(a))
#define INIT() std::ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>P;
const int MAX_N=400+5;
const int INF=0x7fffffff;
const int inf=1000000000;
const double EPS=1e-6;
const ull base=123;
const ll mod=1e9+7;
const double pi=4*atan(1.0);
int eg[MAX_N][MAX_N];
int d[MAX_N];
int main()
{
   
    int money,m1,n,m2,x;
    cin>>money>>m1>>n>>m2>>x;
    int i,j;
    for(i=1;i<=n;i++)
    {
   
        for(j=1;j<=n;j++)
            eg[i][j]=inf;
    }
    fill(d,d+1+n,inf);
    for(i=1;i<=m1;i++)
    {
   
        int l,r;
        scanf("%d%d",&l,&r);
        eg[l][r]=-money;
    }
    for(i=1;i<=m2;i++)
    {
   
        int l,r,value;
        scanf("%d%d%d",&l,&r,&value);
        eg[l][r]=value-money;
    }
    int k;
    for(i=1;i<=n;i++)
    {
   
        if(i==x)
            continue;
        d[i]=eg[x][i];
    }
    d[x]=0;
    int flag;
    for(i=1;i<=n;i++)
    {
   
        flag=0;
        for(j=1;j<=n;j++)
        {
   
            for(k=1;k<=n;k++)
            {
   
                if(j==k)
                    continue;
                if(d[k]>d[j]+eg[j][k])
                {
   
                    //cout<<j<<' '<<k<<endl;
                    flag=1;
                    d[k]=d[j]+eg[j][k];
                }
            }
        }
        if(!flag)
            break;
    }
    if(flag)
    {
   
        cout<<-1<<endl;
    }
    else
    {
   
        int mn=inf;
        for(i=1;i<=n;i++)
        {
   
            mn=min(mn,d[i]);
        }
        cout<<-mn+money<<endl;
    }
}

最短路计数
这题我是觉得bfs方便些,注意每一格第一次出现的时候推入队列,当发现当前步数和这一格的最小步数相同时,这一格的方案数就是原先方案数加上一个方案数。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstdlib>
#include<string>
#include<vector>
#include<list>
#include<map>
#include<set>
#define fi first
#define se second
#define pb push_back
#define me(a,b) memset(a,b,sizeof(a))
#define INIT() std::ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>P;
const int MAX_N=1000000+5;
const int INF=0x7fffffff;
const int inf=1000000000;
const double EPS=1e-6;
const ull base=123;
const ll mod=100003;
const double pi=4*atan(1.0);
vector<int>v[MAX_N];
int d[MAX_N];
int ans[MAX_N];
int vis[MAX_N];
struct node
{
   
    int id,step;
};
queue<node>q;
int main()
{
   
    int n,m;
    cin>>n>>m;
    fill(d,d+1+n,inf);
    int i;
    for(i=1;i<=m;i++)
    {
   
        int l,r;
        scanf("%d%d",&l,&r);
        v[l].pb(r);
        v[r].pb(l);
    }
    q.push(node{
   1,0});
    ans[1]=1;
    vis[1]=1;
    while(!q.empty())
    {
   
        int num=q.front().id;
        int step=q.front().step;
        q.pop();
        for(i=0;i<v[num].size();i++)
        {
   
            int e=v[num][i];
            if(!vis[e])
            {
   
                vis[e]=1;
                q.push(node{
   e,step+1});
                d[e]=step+1;
                //q.push(node{e,step+1});
            }
            if(d[e]==step+1)
            {
   
                ans[e]=(ans[e]+ans[num])%mod;
                //q.push(node{e,step+1});
            }

            //cout<<e<<' '<<d[e]<<endl;
        }
    }

    for(i=1;i<=n;i++)
    {
   
        cout<<ans[i]<<endl;
    }
}

单源最短路径(标准版)
Dijkstra+优先队列优化,我写的有点怪,因为太久没写了,都是自己临时想的,可能跟原先的模板差的有点大。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstdlib>
#include<string>
#include<vector>
#include<list>
#include<map>
#include<set>
#define fi first
#define se second
#define pb push_back
#define me(a,b) memset(a,b,sizeof(a))
#define INIT() std::ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>P;
const int MAX_N=1000000+5;
const int INF=0x7fffffff;
const int inf=1000000000;
const double EPS=1e-6;
const ull base=123;
const ll mod=100003;
const double pi=4*atan(1.0);
struct NODE
{
   
    int to;
    int value;
};
vector<NODE>v[MAX_N];
struct node
{
   
    int id;
    int d;
    bool friend operator<(node a,node b)
    {
   
        return a.d>b.d;
    }
}a[MAX_N];
priority_queue<node>q;
int cost[MAX_N];
int used[MAX_N];
int main()
{
   
    int n,m,x;
    scanf("%d%d%d",&n,&m,&x);
    int i;
    for(i=1;i<=n;i++)
    {
   
        a[i].id=i;
        a[i].d=inf;
    }
    for(i=1;i<=m;i++)
    {
   
        int l,r,value;
        scanf("%d%d%d",&l,&r,&value);
        v[l].pb(NODE{
   r,value});
    }
    a[x].d=0;
    q.push(a[x]);
    while(!q.empty())
    {
   
        node p=q.top();
        q.pop();
        if(used[p.id])
            continue;
        used[p.id]=1;
        for(i=0;i<v[p.id].size();i++)
        {
   
            NODE u=v[p.id][i];
            if(p.d+u.value<a[u.to].d)
            {
   
                a[u.to].d=p.d+u.value;
                q.push(a[u.to]);
            }
        }
    }
    for(i=1;i<=n;i++)
    {
   
        printf("%d%c",a[i].d,i==n?'\n':' ');
    }
}

棋盘
我也不知道为什么我要在最短路的专题里面用dfs,然后就是疯狂超时,给他疯狂剪枝。总之直接dfs肯定超时,就要考虑剪枝,以下可能要剪掉
1.目前用的金币大于已经求得的答案最小值。
2.用一个数组保存到每个点所用金币最小值,如果当前使用金币大于这个点的最小值,那么剪掉。
3.没有颜色的情况,只需要搜索跟上一格颜色相同的情况。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstdlib>
#include<string>
#include<vector>
#include<list>
#include<map>
#include<set>
#define fi first
#define se second
#define pb push_back
#define me(a,b) memset(a,b,sizeof(a))
#define INIT() std::ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>P;
const int MAX_N=1000+5;
const int INF=0x7fffffff;
const int inf=1000000000;
const double EPS=1e-6;
const ull base=123;
const ll mod=100003;
const double pi=4*atan(1.0);
int chess[MAX_N][MAX_N];
int used[MAX_N][MAX_N];
int dir[4][2]= {
   {
   1,0},{
   -1,0},{
   0,-1},{
   0,1}};
int ans=INF;
int m,n;
int d[MAX_N][MAX_N];
void dfs(int x,int y,int flag,int sum)
{
   
    if(x==m&&y==m)
    {
   
        //cout<<sum<<endl;
        ans=min(ans,sum);
        return;
    }
    int i;
    for(i=0; i<4; i++)
    {
   
        int dx=x+dir[i][0];
        int dy=y+dir[i][1];
        if(dx>=1&&dy>=1&&dx<=m&&dy<=m&&used[dx][dy]==0)
        {
   
            if(chess[dx][dy]==chess[x][y])
            {
   
                //cout<<dx<<' '<<dy<<endl;
                used[dx][dy]=1;
                if(sum<ans)
                {
   
                    if(sum<d[dx][dy])
                    {
   
                        d[dx][dy]=sum;
                        dfs(dx,dy,0,sum);
                    }
                }
                used[dx][dy]=0;
            }
            else if(chess[dx][dy])
            {
   
                used[dx][dy]=1;
                if(sum+1<ans)
                {
   
                    if(sum+1<d[dx][dy])
                    {
   
                        d[dx][dy]=sum+1;
                        dfs(dx,dy,0,sum+1);
                    }
                }
                used[dx][dy]=0;
            }
            else if(flag==0)
            {
   
                used[dx][dy]=1;
                chess[dx][dy]=chess[x][y];
                if(sum+2<ans)
                {
   
                    if(sum+2<d[dx][dy])
                    {
   
                        d[dx][dy]=sum+2;
                        dfs(dx,dy,1,sum+2);
                    }
                }
                used[dx][dy]=0;
                chess[dx][dy]=0;
            }
        }
    }
}
int main()
{
   

    int i,j;
    cin>>m>>n;
    for(i=1; i<=n; i++)
    {
   
        int x,y,op;
        scanf("%d%d%d",&x,&y,&op);
        chess[x][y]=++op;
    }
    for(i=1; i<=m; i++)
        for(j=1; j<=m; j++)
            d[i][j]=INF;
    used[1][1]=1;
    dfs(1,1,0,0);
    if(ans==INF)
        ans=-1;
    cout<<ans<<endl;
}

全部评论

相关推荐

赏个offer求你了:友塔HR还专门加我告诉我初筛不通过😂
点赞 评论 收藏
分享
双非坐过牢:非佬,可以啊10.28笔试,11.06评估11.11,11.12两面,11.19oc➕offer
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务