CF-Codeforces Round #420 (Div. 2)-D-Okabe and City

来源:互联网 发布:局域网网络协议 编辑:程序博客网 时间:2024/05/22 16:46

ACM模版

描述

描述
描述

题解

这个题真的有趣,最短路,难点主要是在建图上~~~

这里先说一下题面的误区,我一开始理解为每盏灯只能点亮其所在的行或者列,谁成想并不是这样,而是说能点亮任何行或者列。那是否意味着我们需要考虑他和任何一行或者一列的边呢?实际上并不需要,因为题目中有一个很强的条件,当他要点亮一行或者一列时,前边点亮的就会熄灭,而人无时不刻都要待在光亮区域,所以呢?在每次点亮时,人都要在有灯的地方才行,酱紫的话,我们经过思考后,其实每次点亮时,都只有六个部分有价值,除去灯所在的行或者列外,剩下的四个就是灯所在的行或者列相邻的行或者列,这里我们将这些行或者列抽象为一个点,建边,权值为 1,反向建边,权值为 0。这里我们有一个十分好的 hash 技巧,就是设一个 OFFSET 临界值,凡是等的位置,我们都按顺序默认为在 1OFFSET,而行抽象的点映射到 OFFSET+12OFFSET,列抽象的点映射到 2OFFSET+13OFFSET,酱紫的话,我们建好图后直接一遍 dijkstra 算法即可,注意这里使用一下堆优化……不知道不用堆优化是否会爆了。

最短路好题,建图套路深!

代码

#include <iostream>#include <cstring>#include <vector>#include <queue>#include <map>using namespace std;typedef pair<int, int> pii;const int MAXN = 1e5;const int OFFSET = 1e4 + 10;const int INF = 0x3f3f3f3f;const int DIR[4][2] = {{0, 1}, {0, -1},                       {1, 0}, {-1, 0}};int cnt = 1;struct edge{    int to, cost;    edge() {}    edge(int to_, int cost_) : to(to_), cost(cost_) {}};void add_edge(vector<edge> G[], int r, int c){    G[cnt].push_back(edge(r + OFFSET, 1));    G[cnt].push_back(edge(r + 1 + OFFSET, 1));    G[cnt].push_back(edge(r - 1 + OFFSET, 1));    G[cnt].push_back(edge(c + 2 * OFFSET, 1));    G[cnt].push_back(edge(c + 1 + 2 * OFFSET, 1));    G[cnt].push_back(edge(c - 1 + 2 * OFFSET, 1));    G[r + OFFSET].push_back(edge(cnt, 0));    G[r + 1 + OFFSET].push_back(edge(cnt, 0));    G[r - 1 + OFFSET].push_back(edge(cnt, 0));    G[c + 2 * OFFSET].push_back(edge(cnt, 0));    G[c + 1 + 2 * OFFSET].push_back(edge(cnt, 0));    G[c - 1 + 2 * OFFSET].push_back(edge(cnt, 0));    cnt++;}int n, m, k;int dis[MAXN];int vis[MAXN];pii p[MAXN];vector<edge> E[MAXN];map<pii, int> mpi;void dijkstra(int s){    memset(dis, 0x3f, sizeof(dis));    memset(vis, 0, sizeof(vis));    priority_queue<pii, vector<pii>, greater<pii> > pq;    dis[s] = 0;    pq.push(pii(0, s));    pii tmp;    while (!pq.empty())    {        tmp = pq.top();        pq.pop();        int u = tmp.second;        if (vis[u])        {            continue;        }        vis[u] = 1;        for (int i = 0; i < E[u].size(); i++)        {            edge e = E[u][i];            if (dis[e.to] > dis[u] + e.cost)            {                dis[e.to] = dis[u] + e.cost;                pq.push(pii(dis[e.to], e.to));            }        }    }}int main(int argc, const char * argv[]){    cin >> n >> m >> k;    int r, c;    for (int i = 1; i <= k; i++)    {        scanf("%d%d", &r, &c);        add_edge(E, r, c);        p[i] = make_pair(r, c);        mpi[p[i]] = i;    }    pii t;    for (int i = 1; i <= k; i++)    {        for (int j = 0; j < 4; j++)        {            int x = p[i].first + DIR[j][0];            int y = p[i].second + DIR[j][1];            t = make_pair(x, y);            if (mpi[t])            {                E[i].push_back(edge(mpi[t], 0));            }        }    }    t = make_pair(n, m);    if (!mpi[t])    {        E[n + OFFSET].push_back(edge(k + 1, 0));        E[m + 2 * OFFSET].push_back(edge(k + 1, 0));    }    dijkstra(mpi[pii(1, 1)]);    int ans;    if (mpi[t])    {        ans = dis[mpi[t]];    }    else    {        ans = dis[k + 1];    }    if (ans == INF)    {        ans = -1;    }    cout << ans << '\n';    return 0;}
原创粉丝点击