zoukankan      html  css  js  c++  java
  • 【BZOJ-4289】Tax 最短路 + 技巧建图

    4289: PA2012 Tax

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 168  Solved: 69
    [Submit][Status][Discuss]

    Description

    给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点1到点N的最小代价。起点的代价是离开起点的边的边权,终点的代价是进入终点的边的边权
    N<=100000
    M<=200000

    Input

    Output

    Sample Input

    4 5
    1 2 5
    1 3 2
    2 3 1
    2 4 4
    3 4 8

    Sample Output

    12

    HINT

    Source

    Solution

    比较有技巧的建图

    首先考虑暴力点的建图:

    把每条无向边拆成两条有向边.把每条边看成一个点,对于两条边a->b,b->c

    在这两条边之间连有向边,边权为这两条边的权值的较大值.

    新建源点S,汇点T, S向所有从1连出去的边连边,所有指向n的边向T连边. 求S->T的最短路即可.

    这样的复杂度会达到$O(m^{2})$

    考虑优化一下,有个类似网络流中补流思想的方法:

    考虑利用差值来建边.

    依然把每条边x-y拆成x->y,y->x.

    枚举每个中转点x. 将x的出边按权值排序,x的每条入边向对应的出边连该边权值的边,x的每条出边向第一个比它大的出边连两边权差值的边,x的每条出边向第一个比它小的出边连权值为0的边. 新建源汇S,T S向每条1的出边连权值为该边边权的边.每条n的入边向T连该边权值的边.

    跑S->T的最短路即可.

    这样的复杂度是$O(mlogm)$就可以AC

    顺带提一句,用Dijkstra效率很快

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    using namespace std;
    void Freopen() {freopen("travel.in","r",stdin); freopen("travel.out","w",stdout);}
    #define Pa pair<long long,int>
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define MAXN 200010
    #define INF 1LL<<60
    int N,M;
    struct EdgeNode{int next,to,val;}edge[MAXN<<1],road[MAXN<<3];
    int head[MAXN],cnt=1,first[MAXN<<1],tot=1;
    inline void AddEdge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].val=w;}
    inline void InsertEdge(int u,int v,int w) {AddEdge(u,v,w); AddEdge(v,u,w);}
    inline void AddRoad(int u,int v,int w) {tot++; road[tot].next=first[u]; first[u]=tot; road[tot].to=v; road[tot].val=w;}
    inline bool cmp(int x,int y) {return edge[x].val<edge[y].val;}
    priority_queue<Pa,vector<Pa>,greater<Pa> >q;
    int S,T;
    long long dis[MAXN<<1];
    void Dijkstra()
    {
        for (int i=S; i<=T; i++) dis[i]=INF;
        q.push(make_pair(0,S)); dis[S]=0;
        while (!q.empty())
            {
                int now=q.top().second;
                long long Dis=q.top().first; 
                q.pop();
                if (Dis>dis[now]) continue;
                for (int i=first[now]; i; i=road[i].next)
                    if (dis[now]+road[i].val<dis[road[i].to])
                        dis[road[i].to]=dis[now]+road[i].val,
                        q.push(make_pair(dis[road[i].to],road[i].to));
            }
    }
    int st[MAXN<<1],tp;
    void BuildGraph()
    {
        S=1,T=2*(M+1);
        for (int i=1; i<=N; i++)
            {
                tp=0;
                for (int j=head[i]; j; j=edge[j].next)
                    st[++tp]=j;
                sort(st+1,st+tp+1,cmp);
                for (int j=1; j<=tp; j++)
                    {
                        int now=st[j],suc=st[j+1];
                        if (edge[now].to==N) AddRoad(now,T,edge[now].val);
                        if (i==1) AddRoad(S,now,edge[now].val);
                        AddRoad(now^1,now,edge[now].val);
                        if (j<tp) AddRoad(now,suc,edge[suc].val-edge[now].val),AddRoad(suc,now,0);
                    }
            }
    }
    int main()
    {
    //  Freopen();
        N=read(),M=read();
        for (int x,y,z,i=1; i<=M; i++) x=read(),y=read(),z=read(),InsertEdge(x,y,z);
        BuildGraph();
        Dijkstra();
        printf("%lld
    ",dis[T]);
        return 0;
    }

    小压一波常数,成功跑到rank2..想怒压300ms到rank1时,失误反而慢了300ms....23333

    Orz现场裸跑最短路80分的梁哥....

    貌似还有一种类似于DP的方法?

  • 相关阅读:
    Apache Kafka(七)- Kafka ElasticSearch Comsumer
    【数据库】SQL经典面试题
    【数据库】SQL经典面试题
    【数据库】软件安全测试之SQL注入
    Jmeter代理服务器设置
    代理服务器之趣谈工作原理
    Jmeter之解决烦人的中文乱码问题
    Python之测试webservice接口
    Jmeter录制脚本工具之chrome插件--BlazeMeter
    如何利用Jmeter做代理录制脚本
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5742693.html
Copyright © 2011-2022 走看看