zoukankan      html  css  js  c++  java
  • Tima goes to Xentopia(条件最短路)

    Tima goes to Xentopia

    Tima goes to Xentopia 题目链接

    思路

    首先这题应该用Dijkstra应该是无疑的,但是我们又应该如何表示不同的状态呢,我们定义了(dis[target][red_num][blue_num]) 来表示当前道路的状态,然后和一维的Dijkstra一样去更新其最小状态。

    但是这里有一个地方需要注意直接(dis[455][805][805]),铁定是MLE的,通过仔细读题我们观察到 (k1 * k2 <= 800),于是我们可以定义一个(dis[455][805][100]) 的状态,如果
    (k1 < k2) 我们就交换红蓝道路的颜色。于是这题就变成了一个Dijkstra的裸题了,但是我还是被MLE给坑了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    int head[500], to[3000], nex[3000], value[3000], color[3000], cnt = 1;
    ll dis[500][810][100];
    int visit[500][810][100];
    int n, m, s, t, k1, k2;
    
    struct point {
        int id, r, b;
        ll dis;
        point(int _id, int _r, int _b, ll _dis) : id(_id), r(_r), b(_b), dis(_dis) {}
        bool operator < (const point & t) const {
            return dis > t.dis;
        }
    };
    
    void Dijkstra() {
        memset(dis, 0x3f, sizeof dis);
        priority_queue<point> q;
        dis[s][0][0] = 0;
        q.push(point(s, 0, 0, 0));
        while(!q.empty()) {
            point temp = q.top();
            q.pop();
            if(visit[temp.id][temp.r][temp.b])  continue;
            visit[temp.id][temp.r][temp.b] = 1;
            for(int i = head[temp.id]; i; i = nex[i]) {
                point t = point(to[i], temp.r + (color[i] == 1), temp.b + (color[i] == 2), temp.dis + value[i]);
                if(t.r > k1 || t.b > k2)    continue;//这里一定要判断,否者容易出现不必要的数据,造成数组越界,或者TLE.
                if(t.dis < dis[t.id][t.r][t.b]) {
                    dis[t.id][t.r][t.b] = t.dis;
                    q.push(t);
                }
            }
        }
        printf("%lld
    ", dis[t][k1][k2] == INF ? -1 : dis[t][k1][k2]);
    }
    
    void add(int x, int y, int w, int c) {
        to[cnt] = y;
        nex[cnt] = head[x];
        value[cnt] = w;
        color[cnt] = c;
        head[x] = cnt++;
    }
    
    int main() {
        freopen("in.txt", "r", stdin);
        int x, y, w, c;
        scanf("%d %d %d %d", &n, &m, &k1, &k2);
        bool change = false;
        if(k1 < k2) {
            swap(k1, k2);
            change = true;
        }
        for(int i = 0; i < m; i++) {
            scanf("%d %d %d %d", &x, &y, &w, &c);
            if(change) {
                if(c == 1)  c = 2;
                else if(c == 2) c = 1;
            }
            add(x, y, w, c);
            add(y, x, w, c);
        }
        scanf("%d %d",&s, &t);
        Dijkstra();
        return 0;
    }
    
  • 相关阅读:
    eclipse折叠快捷键
    ubuntu下忘记用户名和密码的解决办法
    ubuntu屏幕分辨率问题
    CentOS 5.X安装LAMP最高版本环境
    CentOS 6.X安装LAMP最高版本环境
    Shell脚本升级CentOS php版本v
    运行yum报错Error: Cannot retrieve metalink for repository: epel. Please verify its path and try again
    批处理测试局域网网络连通性ping1-255
    批处理cmd背景颜色
    CentOS6.4安装LAMP环境
  • 原文地址:https://www.cnblogs.com/lifehappy/p/12810068.html
Copyright © 2011-2022 走看看