zoukankan      html  css  js  c++  java
  • BZOJ4289: PA2012 Tax

    BZOJ4289: PA2012 Tax

    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

    题解Here!

    这个题一眼看去感觉不可做啊。。。
    关键就是建图。。。
    这是一个比较有技巧的建图方式。
    首先考虑暴力点的建图:
    常规操作:把每条无向边拆成两条有向边。
    把每条边看成一个点,对于两条边$a->b,b->c$:
    在这两条边之间连有向边,边权为这两条边的权值的较大值。
    新建源点$S$,汇点$T$,$S$向所有从$1$连出去的边连边,所有指向$n$的边向$T$连边。
    求$S->T$的最短路即可。
    这个方式显然复杂度是$O(m^2)$的,铁定$TLE$。。。
    所以考虑骚操作优化。

    我们用类似网络流中补流思想的方法:考虑利用差值来建边。
    依然把每条边$x-y$拆成$x->y,y->x$。
    枚举每个中转点$x$。
    将$x$的出边按权值排序,$x$的每条入边向对应的出边连该边权值的边,$x$的每条出边向第一个比它大的出边连两边权差值的边,$x$的每条出边向第一个比它小的出边连权值为$0$的边。
    新建源汇$S,T$,$S$向每条$1$的出边连权值为该边边权的边。
    每条$n$的入边向$T$连该边权值的边。
    跑$S->T$的最短路即可。

     

    注:
    1. 此题卡$SPFA$!此题卡$SPFA$!!此题卡$SPFA$!!!重要的事情说三遍!!!所以还是乖乖写堆优化$dijkstra$吧。。。
    2. 记得与路径长度有关的数组、变量都要开$long long$!
    附代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<queue>
    #define MAXN 400010
    #define MAX (1LL<<60)
    using namespace std;
    int n,m,c=1,d=2,s,t;
    int head[MAXN],h[MAXN],stack[MAXN];
    long long path[MAXN];
    bool vis[MAXN];
    struct Edge{
    	int next,to;
    	long long w;
    }edge[MAXN],a[MAXN<<2];
    struct node{
        int x;
    	long long dis;
        bool operator <(const node &p)const{
            return dis>p.dis;
        }
    };
    priority_queue<node> q;
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline bool cmp(const int &p,const int &q){
    	return edge[p].w<edge[q].w;
    }
    inline int relax(int u,int v,long long w){
    	if(path[v]>path[u]+w){
    		path[v]=path[u]+w;
    		return 1;
    	}
    	return 0;
    }
    inline void add_edge(int u,int v,long long w){
    	edge[d].to=v;edge[d].w=w;edge[d].next=h[u];h[u]=d++;
    	edge[d].to=u;edge[d].w=w;edge[d].next=h[v];h[v]=d++;
    }
    inline void add(int u,int v,long long w){
    	a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++;
    }
    void dijkstra(){
        node u,v;
        for(int i=s;i<=t;i++){path[i]=MAX;vis[i]=false;}
        u.x=s;u.dis=path[s]=0;
        q.push(u);
        while(!q.empty()){
            u=q.top();
            q.pop();
            if(!vis[u.x]){
                vis[u.x]=true;
                for(int i=head[u.x];i;i=a[i].next){
                    v.x=a[i].to;
                    if(!vis[v.x]){
                        path[v.x]=min(path[v.x],path[u.x]+a[i].w);
                        v.dis=u.dis+a[i].w;
                        q.push(v);
                    }
                }
            }
        }
    }
    void build(){
    	int top;
    	for(int i=1;i<=n;i++){
    		top=0;
    		for(int j=h[i];j;j=edge[j].next)stack[++top]=j;
    		sort(stack+1,stack+top+1,cmp);
    		for(int j=1;j<=top;j++){
    			int now=stack[j],after=stack[j+1];
    			if(edge[now].to==n)add(now,t,edge[now].w);
    			if(i==1)add(s,now,edge[now].w);
    			add(now^1,now,edge[now].w);
    			if(j<top){
    				add(now,after,edge[after].w-edge[now].w);
    				add(after,now,0);
    			}
    		}
    	}
    }
    void work(){
    	dijkstra();
    	printf("%lld
    ",path[t]);
    }
    void init(){
    	int u,v,w;
    	n=read();m=read();
    	s=1;t=((m+1)<<1);
    	for(int i=1;i<=m;i++){
    		u=read();v=read();w=read();
    		add_edge(u,v,w);
    	}
    	build();
    }
    int main(){
    	init();
    	work();
        return 0;
    }
    
  • 相关阅读:
    HDU 4348 To the moon(可持久化线段树)
    HDU 5875 Function 大连网络赛 线段树
    HDU 5877 2016大连网络赛 Weak Pair(树状数组,线段树,动态开点,启发式合并,可持久化线段树)
    HDU 5876 大连网络赛 Sparse Graph
    HDU 5701 中位数计数 百度之星初赛
    CodeForces 708B Recover the String
    Java实现 蓝桥杯 算法提高 套正方形(暴力)
    ASP.NET生成验证码
    ASP.NET生成验证码
    ASP.NET生成验证码
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9557241.html
Copyright © 2011-2022 走看看