zoukankan      html  css  js  c++  java
  • BZOJ4289 PA2012Tax(最短路)

      一个暴力的做法是把边看成点,之间的边权为两边的较大权值,最短路即可。但这样显然会被菊花图之类的卡掉。

      考虑优化建图。将边拆成两个有向边,同样化边为点。原图中同一条边在新图中的两个点之间连边权为原边权的边。对于原图同一点的出边按权值从小到大排序,权值相邻的由小到大连边权为差值的边,由大到小连边权为0的边。这样就完成了取max的操作。加上超源超汇即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 100010
    #define M 200010
    int n,m,p[M<<1],t=0;
    long long d[M<<1];
    bool flag[M<<1];
    struct data{int to,nxt,len;
    }edge[M<<3];
    struct data3{int x,y,z,i;
    }e[M<<1];
    struct data2
    {
        int x;long long d;
        bool operator <(const data2&a) const
        {
            return d>a.d;
        }
    };
    priority_queue<data2> q;
    void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;}
    void dijkstra()
    {
        while (!q.empty()) q.pop();
        memset(d,42,sizeof(d));d[0]=0;q.push((data2){0,0});
        memset(flag,0,sizeof(flag));
        for (int i=1;i<=m*2+1;i++)
        {
            while (!q.empty()&&flag[q.top().x]) q.pop();
            if (q.empty()) break;
            data2 v=q.top();q.pop();
            flag[v.x]=1;
            for (int j=p[v.x];j;j=edge[j].nxt)
            if (v.d+edge[j].len<d[edge[j].to])
            {
                d[edge[j].to]=v.d+edge[j].len;
                q.push((data2){edge[j].to,d[edge[j].to]});
            }
        }
    }
    bool cmp1(const data3&a,const data3&b)
    {
        return a.x<b.x;
    }
    bool cmp2(const data3&a,const data3&b)
    {
        return a.z<b.z;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4289.in","r",stdin);
        freopen("bzoj4289.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();
        for (int i=1;i<=m;i++)
        e[i].x=e[i+m].y=read(),e[i].y=e[i+m].x=read(),e[i].z=e[i+m].z=read(),e[i].i=i,e[i+m].i=i+m,addedge(i,i+m,e[i].z),addedge(i+m,i,e[i].z);
        sort(e+1,e+m*2+1,cmp1);
        for (int i=1;i<=m*2;i++)
        {
            int t=i;
            while (t<m*2&&e[t+1].x==e[i].x) t++;
            sort(e+i,e+t+1,cmp2);
            for (int j=i;j<t;j++) addedge(e[j].i,e[j+1].i,e[j+1].z-e[j].z);
            for (int j=t;j>i;j--) addedge(e[j].i,e[j-1].i,0);
            i=t;
        }
        for (int i=1;i<=m*2;i++)
        {
            if (e[i].x==1) addedge(0,e[i].i,e[i].z);
            if (e[i].y==n) addedge(e[i].i,m*2+1,e[i].z);
        }
        dijkstra();
        cout<<d[m*2+1];
        return 0;
    }
  • 相关阅读:
    linux-01-04(创建文件夹mkdir,进入目录命令cd,创建文件命令 echo cp vim touch等,批量创建文件操作)
    linux-05(tar命令的使用)
    linux-06(移动命令mv)
    linux-07(复制命令cp)
    linux-08(查看命令历史记录history)
    cookie
    vue-router路由懒加载
    setTimeout async promise执行顺序总结
    forEach陷阱
    函数节流与函数防抖之间的区别
  • 原文地址:https://www.cnblogs.com/Gloid/p/9839201.html
Copyright © 2011-2022 走看看