kuangbin专题四最短路总结

之前的专题一和二是搜索,特别是广搜尤其多。而该专题最短路算法又可以写成广搜形式,真的快写吐了。。
基本的d最短路算法都基本掌握了,不管什么形式的都能较快的写出来,不过听学弟说什么spfa的slf和lll优化倒是没见过,希望以后能学习到吧。所以如何建图才是解决问题的关键。
C - Heavy Transportation
找能到终点的所有路径的最大值。
需要注意,因为要找最大值,那么优先队列先出来的应该是d大的。

#include<iostream>
#include<stdio.h>
#include<queue>
#include<vector>
#include<cstring>
#include<math.h>

using namespace std;
const int maxn = 1005;
const int inf = 0x3f3f3f3f;
struct Edge
{
    int from, to, dist;
    Edge(int _f, int _t, int _d) :from(_f), to(_t), dist(_d) {}
};

struct HeapNode
{
    int d, u;
    bool operator<(const HeapNode &b)const
    {
        return d < b.d;
    }
};

struct Dijkstra
{
    vector<int>G[maxn];
    vector<Edge>edges;
    bool done[maxn];
    int d[maxn];
    int p[maxn];  //father
    int n;
    void init(int n)
    {
        this->n = n;
        for (int i = 0;i < n;i++)
            G[i].clear();
        edges.clear();
        //memset(done, 0, sizeof(done));
        memset(d, -1, sizeof(d));
    }

    void Addedge(int u, int v, int dis)
    {
        edges.push_back(Edge(u, v, dis));
        int Size = edges.size();
        G[u].push_back(Size - 1);
    }

    void dijkstra(int s)
    {
        priority_queue<HeapNode>Q;
        memset(d, -1, sizeof(d));
        memset(done, 0, sizeof(done));
        for (int i = 0;i < G[s].size();i++)
        {
            Edge &e = edges[G[s][i]];
            d[e.to] = max(d[e.to],e.dist);
            Q.push(HeapNode{ d[e.to],e.to });
        }
        done[s] = 1;
        d[s] = 0;
        while (!Q.empty())
        {
            HeapNode x = Q.top();Q.pop();
            int u = x.u;
            if (done[u])continue;
            done[u] = 1;
            for (int i = 0;i < G[u].size();i++)
            {
                Edge &e = edges[G[u][i]];
                if (d[e.to] < min(d[u], e.dist))
                {
                    d[e.to] = min(d[u], e.dist);
                    Q.push(HeapNode{ d[e.to],e.to });
                }
            }
        }
    }

}dij;


int main()
{
    int T;
    int n,m;
    int cas = 1;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d %d", &n, &m);
        dij.init(n);
        int u, v, dist;
        for (int i = 1;i <= m;i++)
        {
            scanf("%d %d %d", &u, &v, &dist);
            u--;v--;
            dij.Addedge(u, v, dist);
            dij.Addedge(v, u, dist);
        }
        dij.dijkstra(0);
        printf("Scenario #%d:\n%d\n\n", cas++, dij.d[n-1]);

    }

}

F - Wormholes
思路:一开始做最短路,不知道这个要怎么做,看了题解知道了。依照题意建个图,然后看有没有负环,如果有负环则说明他能回到过去。

#include<iostream>
#include<cstring>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxm = 5500;
const int maxn = 505;
const int inf = 0x3f3f3f3f;
int N, M, W;

struct Edge
{
    int from, to, dis;
    Edge(int _f, int _t, int _d) :from(_f), to(_t), dis(_d){}
    Edge(){}
}edges[maxm];
int tot;
void addedge(int u, int v, int dist)
{
    edges[tot].from = u;
    edges[tot].to = v;
    edges[tot].dis = dist;
    tot++; 
}
int d[maxn];
bool solve()
{
    memset(d, inf, sizeof(d));
    d[1] = 0;
    for (int i = 1;i < N;i++)
        for (int j = 0;j < tot;j++)
            d[edges[j].to] = min(d[edges[j].to], d[edges[j].from] + edges[j].dis);

    for (int i = 0;i < tot;i++)
        if (d[edges[i].to] > d[edges[i].from] + edges[i].dis)
            return true;
    return false;
}

int main()
{
    int F;
    scanf("%d", &F);
    while (F--)
    {
        tot = 0;
        scanf("%d %d %d", &N, &M, &W);
        int S, E, T;
        for (int i = 1;i <= M;i++)
        {
            scanf("%d %d %d", &S, &E, &T);
            addedge(S, E, T);
            addedge(E, S, T);
        }
        for (int i = 1;i <= W;i++)
        {
            scanf("%d %d %d", &S, &E, &T);
            addedge(S, E, -T);
        }
        if (solve())
            puts("YES");
        else
            puts("NO");
    }
    return 0;
}

M - 昂贵的聘礼
思路:一开始想到一个很巧妙的思路,先建一个虚点,然后这个点到其他物品的距离就是物品的价值,物品之间的价值就由题目那样加。然后在最短路算法中维护每个node的等级区间。
结果当然是wa了,仔细想想还是有点问题的,因为更新的d值不知道是在什么情况下更新的,所以不能共用一个d值。
所以这题正确做法是先枚举最低等级,然后在这个这个区间选物品即可。

#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxn = 105;
const int maxm = 15000;
const int inf = 0x3f3f3f3f;
#pragma GCC optimize(2)
int M, N;
struct Edge
{
    int from, to;
    int dist;
    int Next;
    Edge(int _f,int _t,double _d,int _n):from(_f),to(_t),dist(_d),Next(_n){}
    Edge(){}
}edges[maxm];

struct thing
{
    int cost, level;
}things[maxn];
vector<int>Vec[maxn],v1;
int Cost[maxn][maxn];

struct HeapNode
{
    int d;
    int u;
    HeapNode(int _d,int _u):d(_d),u(_u){}
    HeapNode(){}
    bool operator<(const HeapNode &b)const
    {
        return d > b.d;
    }
};

struct Dijkstra
{
    int head[maxn];
    bool done[maxn];
    int d[maxn];
    int n;
    int tot;
    int Right,Left;
    void init(int n)
    {
        this->n = n;
        memset(head, -1, sizeof(head));
        tot = 0;
    }
    void addedge(int u, int v, int dist)
    {
        edges[tot] = Edge(u, v, dist,head[u]);
        //edges[tot].Next = head[u];
        head[u] = tot++;
    }
    void dijkstra(int s)
    {
        memset(done, 0, sizeof(done));
        for (int i = 0;i <= n;i++)d[i] = inf;
        d[s] = 0;
        //Right = things[s].level + M;

        priority_queue<HeapNode>Q;
        Q.push(HeapNode(d[s], s));
        while (!Q.empty())
        {
            HeapNode x = Q.top();Q.pop();
            int u = x.u;
            if (done[u])continue;
            done[u] = 1;
            for (int i = head[u];~i;i=edges[i].Next)
            {
                Edge &e = edges[i];
                if (things[e.to].level > Right||things[e.to].level<Left)continue;
                if (d[e.to] > d[e.from] + e.dist)
                {
                    d[e.to] = d[e.from] + e.dist;
                    Q.push(HeapNode(d[e.to], e.to));
                }
            }
        }
    }
}dij;

int main()
{
    scanf("%d %d", &M, &N);
    int P, L, X,T,V;
    for (int i = 1;i <= N;i++)
    {
        scanf("%d %d %d", &P, &L, &X);
        things[i].cost = P;
        things[i].level = L;
        v1.push_back(L);
        for (int j = 1;j <= X;j++)
        {
            scanf("%d %d", &T, &V);
            Vec[i].push_back(T);
            Cost[i][T] = V;
        }
    }

    dij.init(N);
    for (int i = 1;i <= N;i++)
    {
        for (int j = 0;j < Vec[i].size();j++)
        {
            int to = Vec[i][j];
            int thecost = Cost[i][to];
            dij.addedge(to, i, thecost);
        }
    }
    sort(v1.begin(), v1.end());
    unique(v1.begin(), v1.end());
    int mincost = inf;
    for(int j=0;j<v1.size();j++)
        for (int i = 1;i <= N;i++)
        {
            dij.Right = v1[j] + M;
            dij.Left = v1[j];
            if (things[i].level<dij.Left || things[i].level>dij.Right)continue;
            dij.dijkstra(i);
            mincost = min(mincost, dij.d[1] + things[i].cost);
        }
    cout << mincost << endl;

O - Extended Traffic
思路:一开始没想到还有负值。直接用dijkstra跑了两发。。真没想到amount竟然还有负值。。另外注意格式问题,并没有空行。。

#include<iostream>
#include<cstring>
#include<stdio.h>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 205;
const int inf = 0x3f3f3f3f;
int score[maxn];
int map[maxn][maxn];
int d[maxn];
bool inque[maxn];
int cnt[maxn];
int N, M;
int dis(int a, int b)
{
    int temp = score[b] - score[a];
    return temp*temp*temp;
}
void spfa()
{
    queue<int>Q;
    Q.push(1);
    d[1] = 0;
    while (!Q.empty())
    {
        int x = Q.front();Q.pop();
        inque[x] = 0;
        for (int i = 1;i <= N;i++)if (map[x][i] != inf)
        {
            if (d[i] > d[x] + map[x][i])
            {
                d[i] = d[x] + map[x][i];
                if (!inque[i])
                {
                    inque[i] = 1;

                    if (cnt[i] <= N)
                        Q.push(i), cnt[i]++;;
                }
            }
        }
    }
}

int main()
{
    int T;
    scanf("%d", &T);
    for (int time = 1;time <= T;time++)
    {
        //printf("\n");
        memset(map, inf, sizeof(map));
        memset(d, inf, sizeof(d));
        memset(inque, 0, sizeof(inque));
        memset(cnt, 0, sizeof(cnt));
        scanf("%d", &N);
        for (int i = 1;i <= N;i++)
        {
            scanf("%d", &score[i]);
        }
        int u, v;
        scanf("%d", &M);
        for (int i = 1;i <= M;i++)
        {
            scanf("%d %d", &u, &v);
            map[u][v] = dis(u, v);
        }

        spfa();
        int q;
        printf("Case %d:\n", time);
        scanf("%d", &q); 
        while (q--)
        {
            scanf("%d", &u);
            if (d[u] == inf || d[u]<3)puts("?");
            else
                printf("%d\n", d[u]);
        }
    }
    return 0;

}

接下来的题目是本专题的精华题!!
P - The Shortest Path in Nya Graph
先看最开始的做法,一开始没想到把layer也当做一个点,结果愚蠢的只要两点有关系就相连,结果re了若干发。。
之后知道了要加虚点,于是把图建成了这样。
这里写图片描述
之后才发现事情的严重性。。这样建之后同层点的距离变成了0。。
所以正确建图如下(学习学习。。)
这里写图片描述
代码如下:

#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>
#include<stdio.h>

using namespace std;
const int maxn = 2e5 + 5;
const int maxm = 6e7 + 5;
const int inf = 0x3f3f3f3f;

int idx[maxn];

struct Edge
{
    int from, to, dist, next;
    Edge(int _f, int _t, int _d, int _next) :from(_f), to(_t), dist(_d), next(_next) {}
    Edge() {}
}edges[maxm];

struct HeapNode
{
    int d, u;
    HeapNode(int _d, int _u) :d(_d), u(_u) {}
    HeapNode() {}
    bool operator<(const HeapNode &b)const
    {
        return d > b.d;
    }
};

struct Dijkstra
{
    vector<int>G[maxn];
    int head[maxn];
    bool done[maxn];
    int d[maxn];
    int n;
    int tot;
    void init(int n)
    {
        this->n = n;
        for (int i = 1;i <= n;i++)
            G[i].clear();
        memset(head, -1, sizeof(head));
        tot = 0;
    }

    void addedge(int u, int v, int dist)
    {
        edges[tot] = Edge(u, v, dist, head[u]);
        head[u] = tot++;
    }

    void dijkstra(int s)
    {
        memset(done, 0, sizeof(done));
        memset(d, inf, sizeof(d));
        d[s] = 0;
        priority_queue<HeapNode>Q;
        Q.push(HeapNode(d[s], s));
        while (!Q.empty())
        {
            HeapNode x = Q.top();Q.pop();
            if (done[x.u])continue;
            done[x.u] = 1;
            for (int i = head[x.u];~i;i = edges[i].next)
            {
                Edge &e = edges[i];
                if (d[e.to] > d[x.u] + e.dist)
                {
                    d[e.to] = d[x.u] + e.dist;
                    Q.push(HeapNode(d[e.to], e.to));
                }
            }
        }
    }
}dij;

bool layer[maxn];
int main()
{
    int T;
    scanf("%d", &T);
    int cas = 1;
    while (T--)
    {
        memset(layer, 0, sizeof(layer));
        int N, M, C;
        scanf("%d %d %d", &N, &M, &C);
        dij.init(2*N);
        for (int i = 1;i <= N;i++)
            scanf("%d", &idx[i]);
        int u, v, w;
        for (int i = 1;i <= M;i++)
        {
            scanf("%d %d %d", &u, &v, &w);
            dij.addedge(u, v, w);
            dij.addedge(v, u, w);
        }
        for (int i = 1;i < N;i++)
            if (layer[i] && layer[i + 1])
                dij.addedge(i + N, i + 1 + N, C), dij.addedge(i + 1 + N, i + 1, C);
        for (int i = 1;i <= N;i++)
        {
            dij.addedge(idx[i] + N, i, 0);
            if (idx[i] > 1)
                dij.addedge(i, idx[i] + N - 1, C);
            if (idx[i] < N)
                dij.addedge(i, idx[i] + N + 1, C);
        }
        dij.dijkstra(1);
        printf("Case #%d: %d\n", cas++, dij.d[N] == inf ? -1 : dij.d[N]);
    }

    return 0;
}

Q - Marriage Match IV
又是一道好题。。
一开始想到一个愚蠢的做法,就是疯狂的跑dij。。然后跑一次就记录边,然后把这些边值改成inf。。结果当然T了。。
看了题解又感叹自己为啥总想不到这么好的想法。。
首先跑两遍dij,记录A到所有点和所有点到B的最小值。然后我们来看这些弧,如果A到该弧的弧顶的距离+弧长+弧尾到B的距离等于最小距离,那么这条弧肯定在最短路中,把它加到网络流中,容量为1,接着跑最大流即可。(是我太菜了。。好题!!!)

#include<iostream>
#include<queue>
#include<cstring>
#include<stdio.h>

using namespace std;

const int maxm = 1e5 + 5;
const int maxn = 1005;
const int inf = 0x3f3f3f3f;


struct Edge
{
    int from, to, dist, next;
    Edge(int _f,int _t,int _d,int _n):from(_f),to(_t),dist(_d),next(_n){}
    Edge(){}
}edges[2][maxm];
int head[2][maxn],tot[2];
int d[2][maxn];
bool done[2][maxn];


struct HeapNode
{
    int d, u;
    HeapNode(int _d,int _u):d(_d),u(_u){}
    HeapNode(){}
    bool operator<(const HeapNode &b)const
    {
        return d > b.d;
    }
};

void addedge(int u, int v, int dist,int idx)
{
    edges[idx][tot[idx]] = Edge(u,v, dist, head[idx][u]);
    head[idx][u] = tot[idx]++;
}

void dijkstra(int s, int idx)
{
    memset(d[idx], inf, sizeof(d[idx]));
    memset(done[idx], 0, sizeof(done[idx]));
    priority_queue<HeapNode>Q;
    d[idx][s] = 0;
    Q.push(HeapNode(d[idx][s], s));
    while (!Q.empty())
    {
        HeapNode x = Q.top();Q.pop();
        int u = x.u;
        if (done[idx][u])continue;
        done[idx][u] = 1;
        for (int i = head[idx][u];~i;i = edges[idx][i].next)
        {
            Edge &e = edges[idx][i];
            if (d[idx][e.to] > d[idx][u] + e.dist)
            {
                d[idx][e.to] = d[idx][u] + e.dist;
                Q.push(HeapNode(d[idx][e.to], e.to));
            }
        }
    }

}


struct Edge2
{
    int from, to, cap, flow;
    Edge2(int u, int v, int c, int f) :from(u), to(v), cap(c), flow(f) {}
    Edge2() {}
};
struct Dinic
{
    int n, m, s, t;
    vector<Edge2>edges;
    vector<int>G[maxn + 50];
    bool vis[maxn + 50];
    int d[maxn + 50];
    int cur[maxn + 50];

    void AddEdge(int from, int to, int cap)
    {
        edges.push_back(Edge2(from, to, cap, 0));
        edges.push_back(Edge2(to, from, 0, 0));
        m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
    }

    void init(int n)
    {
        for (int i = 0;i <= n;i++)G[i].clear();
        edges.clear();
    }

    bool BFS()
    {
        memset(vis, 0, sizeof(vis));
        queue<int>Q;
        Q.push(s);
        d[s] = 0;
        vis[s] = 1;
        while (!Q.empty())
        {
            int x = Q.front();Q.pop();
            for (int i = 0;i < G[x].size();i++)
            {
                Edge2&e = edges[G[x][i]];
                if (!vis[e.to] && e.cap > e.flow)
                {
                    vis[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }

    int DFS(int x, int a)
    {
        if (x == t || a == 0)return a;
        int flow = 0, f;
        for (int &i = cur[x];i < G[x].size();i++)
        {
            Edge2&e = edges[G[x][i]];
            if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow)))>0)
            {
                e.flow += f;
                edges[G[x][i] ^ 1].flow -= f;
                flow += f;
                a -= f;
                if (a == 0)break;
            }
        }
        return flow;
    }
    int Maxflow(int s, int t)
    {
        //cout << edges.size() << endl;
        this->s = s;this->t = t;
        int flow = 0;
        while (BFS())
        {
            memset(cur, 0, sizeof(cur));
            flow += DFS(s, inf);
        }
        return flow;
    }

}dinic;

void init()
{
    tot[0] = tot[1] = 0;
    memset(head, -1, sizeof(head));
}

int main()
{
    int Time;
    scanf("%d", &Time);
    while (Time--)
    {
        init();
        int n, m;
        scanf("%d %d", &n, &m);
        dinic.init(n);
        int a, b, c;
        for (int i = 1;i <= m;i++)
        {
            scanf("%d %d %d", &a, &b, &c);
            if (a == b)continue;
            addedge(a, b, c, 0);
            addedge(b, a, c, 1);
        }
        int S, T;
        scanf("%d %d", &S, &T);
        dijkstra(S, 0);
        dijkstra(T, 1);
        int themin = d[0][T];
        for (int i = 0;i < tot[0];i++)
        {
            Edge &e = edges[0][i];
            if (d[0][e.from] + e.dist + d[1][e.to] == themin)
                dinic.AddEdge(e.from, e.to, 1);
        }
        printf("%d\n",dinic.Maxflow(S, T));
    }
}

R - 0 or 1
多校的题不愧是多校的题,就是难。。
解题的关键在于如何看出这个模型的本质。
题目给了3个条件,我们从图论的角度来思考问题,可以得到下面3个结论。
1.X12+X13+…X1n=1 于是1号节点的出度为1

2..X1n+X2n+…Xn-1n=1 于是n号节点的入度为1

3.∑Xki =∑Xij 于是2~n-1号节点的入度必须等于出度。
3个条件等价于一条从1号节点到n号节点的路径,题目要求总代价最小,因此最优解答案就是最短路。
所以,我们直接读入边权,跑1到n的最短路即可。记最短路为path。
然而并没有完。。。
以上情况设为A。
情况B:
从1出发,走一个环(至少经过1个点,即不能是自环),回到1;从n出发,走一个环(同理),回到n。
容易验证,这是符合题目条件的。且A || B为该题要求的充要条件。
由于边权非负,于是两个环对应着两个简单环。
因此我们可以从1出发,找一个最小花费环,记代价为c1,再从n出发,找一个最小花费环,记代价为c2。(只需在最短路算法更新权值时多加一条记录即可:if(i==S) cir=min(cir,dis[u]+g[u][i]))
故最终答案为min(path,c1+c2)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
using namespace std;
const int maxn = 355;
const int inf = 0x3f3f3f3f;
int cost[maxn][maxn];
bool inq[maxn];
int d[maxn];
int Q[maxn], front,tot;
int n;
void spfa(int s)
{
    memset(inq, 0, sizeof(inq));
    front=tot = 0;
    for (int i = 1;i <= n;i++)
    {
        if (i == s)
            d[i] = inf, inq[i] = false;
        else
        {
            d[i] = cost[s][i];
            inq[i] = 1;
            Q[tot++] = i;
        }
    }

    while (front!=tot)
    {
        int u = Q[front++];
        inq[u] = 0;
        for (int i = 1;i <= n;i++)
        {
            if (d[i] > d[u] + cost[u][i])
            {
                d[i] = d[u] + cost[u][i];
                if (!inq[i])
                {
                    inq[i] = 1;
                    Q[tot++] = i;
                    if (tot >= maxn)tot = 0;
                }

            }
        }
        if (front >= maxn)front = 0;
    }


}

int main()
{

    while (~scanf("%d", &n))
    {
        for (int i = 1;i <= n;i++)
            for (int j = 1;j <= n;j++)
                scanf("%d", &cost[i][j]);
        spfa(1);
        int loop1 = d[1];
        int ans = d[n];
        spfa(n);
        int loop2 = d[n];
        ans = min(ans, loop1 + loop2);
        printf("%d\n", ans);
    }
    return 0;
}

S - Layout
第一次碰见差分约束的概念。。一开始看这题不知道如何建图,看了题解才有点明白。
我们可以设j>i。
那么依据题意有
1,d[j]-[i]<=Like[i][j]
2,d[j]-d[i]>=DisLike[i][j]
我们当然得构造成<=的样子,也就是最大可以离多远,而求最短路就能使所有条件都满足。所以把2式转换成d[i]-d[j]<=DisLike[i][j]。然后依据这个建图。
当有负环时,则说明不能满足所有条件,输出-1。
当d[N]=inf时,也就是可以放到最远处,输出-2.
其他情况输出d[N]。else if打成if wa了几发很难受。。
代码如下:

#include<iostream>
#include<cstring>
#include<stdio.h>
#include<queue>
using namespace std;
const int maxm = 2e4 + 5;
const int maxn = 1005;
const int inf = 0x3f3f3f3f;
struct Edge
{
    int from, to, dist, next;
    Edge(int _f,int _t,int _d,int _n):from(_f),to(_t),dist(_d),next(_n){}
    Edge(){}
}edges[maxm];
int tot;
int head[maxn];
void addedge(int u, int v, int dis)
{
    edges[tot] = Edge(u, v, dis, head[u]);
    head[u] = tot++;
}

int d[maxn];
bool inq[maxn];
int cnt[maxn];
int N, ML, MD;
bool spfa(int s)
{
    memset(d, inf, sizeof(d));
    memset(cnt, 0, sizeof(cnt));
    memset(inq, 0, sizeof(inq));
    queue<int>Q;
    Q.push(s);
    inq[s] = 1;
    cnt[s] = 1;
    d[s] = 0;
    while (!Q.empty())
    {
        int u = Q.front();Q.pop();
        inq[u] = 0;
        for (int i = head[u];~i;i = edges[i].next)
        {
            Edge &e = edges[i];
            if (d[e.to] > d[u] + e.dist)
            {
                d[e.to] = d[u] + e.dist;
                if (!inq[e.to])
                {
                    inq[e.to] = 1;
                    Q.push(e.to);
                    cnt[e.to]++;
                    if (cnt[e.to] > N)return 0;
                }
            }
        }
    }
    return 1;
}

int main()
{


    while (~scanf("%d %d %d", &N, &ML, &MD))
    {
        memset(head, -1, sizeof(head));
        tot = 0;
        int A, B, D;
        for (int i = 1;i <= ML;i++)
        {
            scanf("%d %d %d", &A, &B, &D);if (A > B)swap(A, B);
            addedge(A, B, D);
        }
        for (int i = 1;i <= MD;i++)
        {
            scanf("%d %d %d", &A, &B, &D);if (A > B)swap(A, B);
            addedge(B, A, -D);
        }
        if (!spfa(1))
            puts("-1");
        else if (d[N] == inf)puts("-2");
        else
            printf("%d\n", d[N]);
    }

}

总结:做题最重要的是转换思维。要学会将一道让人不知如何下手的题,转换成已有的模型。多多刷题吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值