avatar
fireworks99
keep hungry keep foolish

POJ 1502 MPI Maelstrom

Description

n个点(1~n)

半个矩阵表示两点距离,x表示无穷大。(自己到自己的距离为0,矩阵里不包含这部分)

求1到所有点中最远点的最小距离

传送门

prepare

字符串转int

#include <cstdio>
#include <string>
#include <iostream>
using namespace std;

int main()
{
    string s;
    cin >> s;
    int a = atoi(s.c_str());
    cout << a << '\n';
    return 0;
}

更多https://blog.csdn.net/u010510020/article/details/73799996

https://blog.csdn.net/u013497977/article/details/50908342

Floyd

邻接矩阵存图,最短路更新在里面

Code of Floyd

#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;///最短路、最小生成树

int n;
int mp[105][105];

void floyd()
{
    for(int k = 1; k <= n; ++k)
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
                if(mp[i][j] > mp[i][k] + mp[k][j])
                    mp[i][j] = mp[i][k] + mp[k][j];
    int ans = -1;
    for(int i = 1; i <= n; ++i)
        if(mp[1][i] > ans)
            ans = mp[1][i];
    cout << ans << '\n';
}

int main()
{
    scanf("%d", &n);
    memset(mp, INF, sizeof(mp));
    for(int i = 1; i <= n; ++i)
        mp[i][i] = 0;
    string s;
    for(int i = 2; i <= n; ++i)
        for(int j = 1; j < i; ++j)///我常犯的错误:都int j了,还++i
        {
            cin >> s;
            if(s == "x")
                mp[i][j] = mp[j][i] = INF;
            else
                mp[i][j] = mp[j][i] = atoi(s.c_str());
        }
    floyd();
    return 0;
}

Bellman_Ford

结构体存边,以“点数次”(n)遍历所有边(cnt)去松弛

Code of Bellman_Ford

#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;

int n, dis[105];

int cnt;
struct edge
{
    int from, to, w;
} a[10005];

void add(int from, int to, int w)
{
    a[cnt].from = from;
    a[cnt].to = to;
    a[cnt].w = w;
    cnt++;
    a[cnt].from = to;
    a[cnt].to = from;
    a[cnt].w = w;
    cnt++;
}

///现在看看这算法也挺暴力的:以“点数次”(n)遍历所有边(cnt)去松弛
bool Bellman_Ford(int start)///以遍历边为基础
{
    dis[start] = 0;
    int tot = n;
///n次松弛(这算法好牛,看看怎么实现的。Later,算了,能用就行)
    while(tot--)
    {
        bool flag = 0;///优化
        for(int i = 0; i < cnt; ++i)///遍历所有边
            if(dis[ a[i].to ] > dis[ a[i].from ] + a[i].w)
            {
                flag = 1;
                dis[ a[i].to ] = dis[ a[i].from ] + a[i].w;
            }
        if(!flag)
            break;
    }
    for(int i = 0; i < cnt; ++i)
        if(dis[ a[i].to ] > dis[ a[i].from ] + a[i].w)
            return 0;
    return 1;
}

int main()
{
    scanf("%d", &n);
    memset(dis, INF, sizeof(dis));
    cnt = 0;
    string s;
    for(int i = 2; i <= n; ++i)
        for(int j = 1; j < i; ++j)
        {
            cin >> s;
            if(s == "x")
                add(i, j, INF);
            else
                add(i, j, atoi(s.c_str()));
        }
    if(Bellman_Ford(1))
    {
        int ans = -1;
        for(int i = 1; i <= n; ++i)
            if(dis[i] > ans && dis[i] != INF)
                ans = dis[i];
        cout << ans << '\n';
    }
    return 0;
}

Dijkstra

每次找到离源点最近的一个顶点,然后以该顶点为中心,然后得到源点到其他顶点的最短路径。贪心算法。

Code of Dijkstra

#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;

int n;

int cnt;
struct edge
{
    int from, to, w, pre;
} a[10005];

bool vis[105];
int head[105], dis[105];

void add(int from, int to, int w)
{
    a[cnt].from = from;
    a[cnt].to = to;
    a[cnt].w = w;
    a[cnt].pre = head[from];
    head[from] = cnt;
    cnt++;
    a[cnt].from = to;
    a[cnt].to = from;
    a[cnt].w = w;
    a[cnt].pre = head[to];
    head[to] = cnt;
    cnt++;
}

void init()
{
    cnt = 0;
    for(int i = 0; i <= n; ++i)
    {
        dis[i] = INF;
        head[i] = -1;
        vis[i] = 0;
    }
}

///分两部分①②
void dijkstra(int start)
{
    dis[start] = 0;
    int pos = start;
    int mmin;
    while(pos != -1)
    {
        ///①利用当前点更新未连入图的点到起点的最短距离
        ///注意:pos是中转点,不再是a[i].from!
        for(int i = head[pos]; ~i; i = a[i].pre)
        {
            if(vis[ a[i].to ])
                continue;
            if(dis[ a[i].to ] == INF || dis[ a[i].to ] > dis[pos] + a[i].w)
                dis[ a[i].to ] = dis[pos] + a[i].w;
        }
        vis[pos] = 1;

        ///②找到下一个距离起点最近的未连入线的点
        pos = -1;
        mmin = -1;
        for(int i = 1; i <= n; ++i)
            if(!vis[i] && dis[i] != INF && (dis[i] < mmin || mmin == -1))
            {
                mmin = dis[i];
                pos = i;
            }
    }
    return ;
}

int main()
{
    scanf("%d", &n);
    init();
    string s;
    for(int i = 2; i <= n; ++i)
        for(int j = 1; j < i; ++j)
        {
            cin >> s;
            if(s == "x")
                add(i, j, INF);
            else
                add(i, j, atoi(s.c_str()));
        }
    dijkstra(1);
    int ans = -1;
    for(int i = 1; i <= n; ++i)
        if(dis[i] > ans && dis[i] != INF)
            ans = dis[i];
    cout << ans << '\n';
    return 0;
}

spfa

感觉像是广义的dijkstra,“最短路期望”…

Code of spfa

#include <queue>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int INF = 0x3f3f3f3f;

int n;

int cnt;
struct edge
{
    int from, to, w, pre;
} a[10005];

bool vis[105];///表示是否在队列里
int head[105], dis[105], times[105], tot, sum;

void add(int from, int to, int w)
{
    a[cnt].from = from;
    a[cnt].to = to;
    a[cnt].w = w;
    a[cnt].pre = head[from];
    head[from] = cnt;
    cnt++;
    a[cnt].from = to;
    a[cnt].to = from;
    a[cnt].w = w;
    a[cnt].pre = head[to];
    head[to] = cnt;
    cnt++;
}

void init()
{
    cnt = 0;
    for(int i = 0; i <= n; ++i)
    {
        dis[i] = INF;
        head[i] = -1;
        vis[i] = 0;
        times[i] = 0;
    }
}

bool spfa(int start)
{
    deque<int> q;
    dis[start] = 0;
    q.push_front(start);
    vis[start] = 1;///表示在队列里
    tot = 1, sum = 0;
    while(q.size())
    {
        int first = q.front();
        q.pop_front();
        vis[first] = 0;
        tot--;
        sum -= dis[first];

///同dijkstra,以first为中转点,而非a[i].from
        for(int i = head[first]; ~i; i = a[i].pre)
        {
            int t = a[i].to;
            if(dis[t] > dis[first] + a[i].w)
            {
                dis[t] = dis[first] + a[i].w;
                if(!vis[t])
                {
                    vis[t] = 1;
                    if(q.empty() || dis[t] > dis[q.front()] || dis[t] * tot >= sum)
                        q.push_back(t);
                    else
                        q.push_front(t);
                    sum += dis[t];
                    tot++;
                    if(++times[t] >= n)///这里是t
                        return 0;
                }
            }
        }
    }
    return 1;
}

int main()
{
    scanf("%d", &n);
    init();
    string s;
    for(int i = 2; i <= n; ++i)
        for(int j = 1; j < i; ++j)
        {
            cin >> s;
            if(s == "x")
                add(i, j, INF);
            else
                add(i, j, atoi(s.c_str()));
        }
    if(spfa(1))
    {
        int ans = -1;
        for(int i = 1; i <= n; ++i)
            if(dis[i] > ans && dis[i] != INF)
                ans = dis[i];
        cout << ans << '\n';
    }
    return 0;
}
Site by Baole Zhao | Powered by Hexo | theme PreciousJoy