Skip to content

Pro4_WA

原始文件为 CPP 代码,本文是转换后的 Markdown 文件。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 505;
const int INF = 1000005;
const int INF_SQ = 1001;

struct Edge
{
    int type, from, to, weight;
    Edge(int y, int f, int t, int w) : type(y), from(f), to(t), weight(w) {}
    bool operator<(const Edge& e2) { return weight < e2.weight; }
};

struct HeapNode
{
    int value, pos;
    HeapNode(int p,int v):pos(p),value(v){}
    bool operator < (const HeapNode& other) const
    {
        return value > other.value;
    }
};

struct Dijkstra
{
    vector<int> adjG[maxn];
    vector<Edge> edges;

    int n;
    bool visit[maxn];
    int easyedge[maxn];
    int hardedge[maxn];

    void init(int n)
    {
        this->n = n;
        for(int i = 0; i <= n; ++i) adjG[i].clear();    
        for(int i = 0; i <= n; ++i) easyedge[i] = INF;
        for(int i = 0; i <= n; ++i) hardedge[i] = INF;
        memset(visit, false, sizeof(visit));  
        edges.clear();
    }

    void add_edge(int type, int from,int to,int weight)
    {
        adjG[from].push_back(edges.size());
        edges.push_back( Edge{type,from,to,weight} );
    }

    int get_shortest(int node)
    {
        return min(hardedge[node], easyedge[node]);
    }

    void dijkstra(int root) 
    {  
        priority_queue<HeapNode> Q;     

        visit[root] = false; easyedge[root] = 0; hardedge[root] = 0;
        Q.push((HeapNode){root, 0});  
        while(!Q.empty()) 
        {    
            HeapNode x = Q.top(); Q.pop();    
            int u = x.pos;

            if(u == n) break; if(visit[u]) continue;   
            visit[u] = true;    

            // printf("dijkstra(%d)\n", u);
            for(int i = 0; i < adjG[u].size(); ++i)
            {
                Edge& e = edges[ adjG[u][i] ]; 
                int v = e.to; int type = e.type; if(visit[v]) continue;
                if(type)
                {
                    // 走小路,只能从大路转到小路
                    if(hardedge[v] > easyedge[u] + e.weight)
                    {
                        hardedge[v] = min(hardedge[v], easyedge[u] + e.weight);
                        Q.push( HeapNode {v, min(hardedge[v], easyedge[v])} );
                    }
                }else
                {
                    // 走大路,可以从小路转到大路,也可以从大路转到大路
                    if(easyedge[v] > min(hardedge[u]+e.weight, easyedge[u]+e.weight))
                    {
                        easyedge[v] = min(hardedge[u] + e.weight, easyedge[u] + e.weight);
                        Q.push( HeapNode {v, min(hardedge[v], easyedge[v])} );
                    }
                }
            }
            // for(int i = 1; i <= n; ++i)
            // {
            //     printf("%d: hard=%d, easy=%d\n", i, hardedge[i], easyedge[i]);
            // }
        } 
    }
};

int hardedge[maxn][maxn];
void floyd(int n)
{
    for(int k = 1; k <= n; ++k)
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
                hardedge[i][j] = min(hardedge[i][j], hardedge[i][k]+hardedge[k][j]);
}


int main()
{
    for(int i = 0; i < maxn; ++i)
        for(int j = 0; j < maxn; ++j) hardedge[i][j] = INF;
    for(int i = 0; i < maxn; ++i) hardedge[i][i] = 0;

    // freopen("in2.txt", "r", stdin);
    int n, m; scanf("%d%d", &n, &m);

    Dijkstra d{}; d.init(n);
    for(int i = 0; i < m; ++i)
    {
        int type, from, to, weight;
        scanf("%d%d%d%d", &type, &from, &to, &weight);
        if(type)
        {
            hardedge[from][to] = hardedge[to][from] = weight;
        }else
        {
            d.add_edge(0, from, to, weight);
            d.add_edge(0, to, from, weight);
        }
    }

    floyd(n);
    for(int i = 1; i <= n; ++i)
    {
        for(int j = 1; j <= n; ++j)
        {
            if(hardedge[i][j] > INF_SQ) continue;

            int weight = hardedge[i][j] * hardedge[i][j];
            if(weight > 0) d.add_edge(1, i, j, weight);
        }
    }
    d.dijkstra(1);
    cout << d.get_shortest(n) << endl;

    return 0;
}