avatar
fireworks99
keep hungry keep foolish

LightOJ 1074 Extended Traffic(The shortest path)

Description

给出n个点的权值(不超过20),点 i 到点 j 之间的距离(如果可达)为(a[j] - a[i]) ^ 3,求到查询点的最短路径

Analyze

单向边,可有负权边,可含负权环 -> 用spfa叭

若某个点在负权环里(++times[to] > n),那么从点to出发所能到达的点(无论是否在负权环里)到起点的距离都是无限小,可以DFS枚举所有可达点并标记

(补充一下:若是单纯求负权环上所有点,应该与强连通分量有关,不仅仅是DFS这么简单)

Code

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

int n, val[MAX_N];

struct edge
{
    int to, w, pre;
} e[50005];

int cnt, head[50005], dis[MAX_N], vis[MAX_N], times[MAX_N], through_circle[MAX_N];

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

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

///这些点不仅是负环上的点,还有不在负环上但最短路经由负环的点!
void DFS(int now)
{
    through_circle[now] = 1;
    for(int i = head[now]; ~i; i = e[i].pre)
        if(!through_circle[ e[i].to ])
            DFS(e[i].to);
}

void spfa()
{
    dis[1] = 0;
    queue<int> q;
    q.push(1);
    vis[1] = 1, times[1] = 1;
    while(!q.empty())
    {
        int now = q.front();
        q.pop();
        vis[now] = 0;
        for(int i = head[now]; ~i; i = e[i].pre)
        {
            int to = e[i].to;
            if(dis[to] > dis[now] + e[i].w)
            {
                dis[to] = dis[now] + e[i].w;
                if(!through_circle[to] && !vis[to])
                    q.push(to), vis[to] = 1;
                if(++times[to] > n)
                    DFS(to);
            }
        }
    }
}

int main()
{
    int _, tot = 1;
    scanf("%d", &_);
    while(_--)
    {
        scanf("%d", &n);
        init();
        for(int i = 1; i <= n; ++i)
            scanf("%d", &val[i]);
        int num, u, v, w;
        scanf("%d", &num);
        for(int i = 0; i < num; ++i)
        {
            scanf("%d %d", &u, &v);
            w = (val[v] - val[u])*(val[v] - val[u])*(val[v] - val[u]);
            add(u, v, w);
        }
//        Dijkstra();
        spfa();

        int q;
        cout << "Case " << tot++ << ":\n";
        scanf("%d", &num);
        while(num--)
        {
            scanf("%d", &q);
            ///cout << (dis[q] <= 3 ? '?' : dis[q]) << '\n';
            if(dis[q] < 3 || dis[q] == INF || through_circle[q] == 1)
                cout << '?' << '\n';
            else
                cout << dis[q] << '\n';
        }
    }
    return 0;
}

补充:三目运算符后面两者的类型需要一致

dis[q] <= 3 ? '?' : dis[q]

以上代码该输出’?’的时候输出了63(?的ASCLL码)

Site by Baole Zhao | Powered by Hexo | theme PreciousJoy