zoukankan      html  css  js  c++  java
  • ccf 2017 12

    附上代码:

    #include<stdio.h>
    #include<string.h>
    #define inf 0x7fffffff
    #include<iostream>
    #include<algorithm>
    #include<queue>
    using namespace std;
    typedef long long ll;
    const int MAXM = 1e6 + 5;
    int n, m;
    typedef struct NODE
    {
        int to;
        ll temp;
        ll cost;
        int ff;
        friend bool operator < (const NODE &a, const NODE &b) {
            return a.cost > b.cost;
        }
    }node;
    typedef struct Edge
    {
        int from;///起点
        ll temp;///记录权值
        int f;///标记小路
        int next;
        int to;
        ll w;
    } edge;
    edge maps[MAXM];
    int head[505];
    ll dist[505];
    int vids[505];
    int cnt;
    void creat ()
    {
        for(int i=0; i<505; i++)
            head[i]=-1;
        cnt=0;
    }
    void add(int t,int u,int v,ll w)
    {
        maps[cnt].f = t;
        maps[cnt].from = u;
        maps[cnt].to=v;
        maps[cnt].w=w;
        maps[cnt].next=head[u];///一开始放置为-1,-1的条件就可以跳出
        ///下一步接着储存,head[u]的值,就是前面的位置
        head[u]=cnt++;///head[u]会得到这条线的值
    }
    ll dijkstra(int s,int t)
    {
        for(int i=0; i<505; i++)
        {
            vids[i]=0;
            dist[i]=inf;
        }
        priority_queue<node>que;
        node begins;
        begins.to = s;
        begins.temp = 0;
        begins.cost = 0;
        begins.ff = 0;
        que.push(begins);
        while(!que.empty())
        {
            node ends=que.top();
            que.pop();
            if(!vids[ends.to])
            {
                vids[ends.to]=1;
                dist[ends.to]=ends.cost;
                for(int i = head[ends.to]; ~i; i = maps[i].next)
                {
                    int to = maps[i].to;
                    ll w = maps[i].w;
                    int flag = maps[i].f;
                    if(!vids[to])
                    {
                        node ans;
                        ans.to=to;
                        if(ends.ff == 0 && flag == 0)
                        {
                            ans.cost = ends.cost + w;
                            ans.ff = flag;
                            ans.temp = 0;
                        }
                        else if(ends.ff == 1 && flag == 0)
                        {
                            ans.cost = ends.cost + w;
                            ans.ff = flag;
                            ans.temp = 0;
                        }
                        else if(ends.ff == 1 && flag == 1)
                        {
                            ans.cost = ends.cost - (ends.temp * ends.temp) + (ends.temp + w) * (ends.temp + w);
                            ans.ff = flag;
                            ans.temp = ends.temp + w;
                        }
                        else if(ends.ff == 0 && flag == 1)
                        {
                            ans.cost = ends.cost + (w * w);
                            ans.ff = flag;
                            ans.temp = w;
                        }
                        que.push(ans);
                    }
                }
            }
        }
        if(dist[t] == inf)
        {
            return -1;
        }
        else
        {
            return dist[t];
        }
    }
    int main()
    {
       while(~scanf("%d%d",&n, &m))
       {
           creat();
           int t, a, b;
           long long c;
           for (int i = 0; i < m; i ++) {
               scanf("%d%d%d%lld",&t, &a, &b, &c);
               add(t, a, b, c);
               add(t, b, a, c);
           }
           ll re = dijkstra(1, n);
           printf("%lld
    ",re);
       }
        return 0;
    }
    #include <iostream>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    using namespace std;
    typedef long long LL;
    class Edge{
    public:
        Edge(){}/*无参构造函数 */
    public:
        int u, v, w, next, flag;
        /* u - 起点
           v - 终点
           w - 边权
           next - 同个起点的前一条边
           flag - 标记是否是小路
        */
    };
    class Malash_map{
    public:
        Malash_map(){
        }
        void Init(){
            for(int i = 0; i < 505; i ++){
                head[i] = -1;
            }
            tot = 0;
        }//初始化链式前向星
        void add(int u, int v, int w, int flag){//添加一条单向边
            arr[tot].u = u, arr[tot].v = v, arr[tot].w = w, arr[tot].flag = flag;
            arr[tot].next = head[u], head[u] = tot ++;
        }
    public:
        int head[505], tot;
        Edge arr[int(2e5 + 500)];
    };//链式前向星
    int vids[505];//标记这个点是否已经被拓展过
    LL dist[505];//从1到n这个点的最短路径
    Malash_map M;
    class Node{
    public:
        Node(int _v, int _f, LL _min_d, LL _cost):v(_v), f(_f), min_dist(_min_d), cost(_cost){}
        friend bool operator< (const Node &a, const Node &b){
            return a.cost > b.cost;
        }//将小于号重载于大于号,那么就能保证优先队列维护的是较小的路径先出队列
    public:
        int v, f;
        LL min_dist, cost;
    };
    LL dijkstra(int s, int t){
        for(int i = 0; i < 505; i ++){
            vids[i] = 0, dist[i] = __LONG_LONG_MAX__;
        }//初始化,肯定所有的点没有被访问过,所有的距离都是无穷远
        priority_queue<Node>que;//优先队列,维护较短的路径先出队列
        while(!que.empty()) que.pop();//清空优先队列
        Node begins(s, 0, 0, 0);//构造起点
        que.push(begins);//将起点放入优先队列
        while(!que.empty()){
            Node temp = que.top();
            que.pop();//取出对应的优先队列中的第一个点,即当前到某个点的最短路径
            if(vids[temp.v] == 1){//如果这个点被拓展过,那么证明这个点的最短路径
            //以及以这个点为起点的边肯定都被拓展过,那么就没有必要再拓展一次
                continue;
            }
            vids[temp.v] = 1;//标记这个点已经被拓展
            dist[temp.v] = min(dist[temp.v], temp.cost);//保留路径最小值
            if(temp.v == t){//如果已经找到了终点,那么没有必要再去拓展了
            //拓展其他都没有必要,所以可以剪枝做一个小优化,直接返回结果
                return dist[t];
            }
            for(int i = M.head[temp.v]; i != -1; i = M.arr[i].next){
                //开始拓展以temp.v为起点的所有相邻边,然后构造出对应的Node新点
                Node en(M.arr[i].v, M.arr[i].flag, temp.min_dist, temp.cost);
                if(!vids[en.v]){//如果这个新点没有被走过,即没有拓展出最短路径
                //那么这个点就应该被拓展
                    if((temp.f == 0 || temp.f == 1) && en.f == 0){
                        //考虑从大路->大路,小路->大路,处理的结果都是一样的如下
                        en.min_dist = 0, en.cost += M.arr[i].w;
                        //将现在连续走的小路的总数变为0,然后更新对应的cost花费
                    }
                    else{
                        en.cost = en.cost - (en.min_dist * en.min_dist) + (en.min_dist + M.arr[i].w) * (en.min_dist + M.arr[i].w); 
                        //假设连续走了的小路和为(a + b + c)
                        //那么又走了段小路d
                        //那么将前面得到的cost - (a + b + c)的平方 + (a + b + c + d)的平方,得到的是到当前的点的最小值
                        //然后更新练习走了的小路的和为(a + b + c + d)
                        en.min_dist += M.arr[i].w;
                    }
                    que.push(en);//将得到的点放入优先队列,优先队列会保证每次取出优先队列中最小的点,进行拓展。
                }
            }
        }
        return dist[t];//返回答案
    }
    int main(){
        int n, m;
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        while(cin >> n >> m){
            M.Init();
            for(int i = 0; i < m; i ++){
                int f, u, v, w;
                cin >> f >> u >> v >> w;
                M.add(u, v, w, f);//添加双向边
                M.add(v, u, w, f);
            }
            LL ans = dijkstra(1, n);
            cout << ans << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    libubox组件(1)——usock
    linux 块设备驱动(五)——块设备应用层的操作
    linux 块设备驱动(四)——简单的sbull实例
    linux 块设备驱动 (三)块设备驱动开发
    linux 块设备驱动(二)——块设备数据结构
    CUDA:零拷贝主机内存
    《无法触碰》
    CUDA: 流
    CUDA: 原子操作
    CUDA:纹理内存
  • 原文地址:https://www.cnblogs.com/qq136155330/p/9683000.html
Copyright © 2011-2022 走看看