zoukankan      html  css  js  c++  java
  • bzoj 4289: 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

    HINT

    Source

    首先考虑暴力的做法,把无向边拆为两条,把边当做点,如果两条边之间有交点,就连边,边权为两个点所代表的边的边权较大者;

    然后这样的边数为n^2,然后我们可以考虑用差分的思想优化连边;

    我们把原图中每个点的出边进行排序,然后边权小的点往边权大的点连差值的权值,然后大的往小的连0的权值,然后每条边对应的两个点连边权为原图权值的边;

    这样做相当于从小往大走,用差分累加答案,然后从大的往小走最大值就是自己,所以权值为0,

    然后通过第三种边完成了入边和出边的转化,中间的边权代表入边的边权,并且割断了该入边与上一条出边的关系;

    然后特殊处理S,T即可,Spfa 跑不过,系统堆Dijkstra跑得挺快的;

    //MADE BY QT666
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #define RG register
    using namespace std;
    typedef long long ll;
    const int N=500050;
    const int M=2000050;
    int n,m,cnt=1,tot,sta,T,tmp,to[M],edg[M],nxt[M],q[N],val[N],id[N],vis[N];
    ll dis[N];
    struct data{int x,y,z;}a[N];  
    struct graph{  
        int head[N];  
        void lnk(int x,int y,int z){
    	to[++tot]=y; edg[tot]=z; nxt[tot]=head[x]; head[x]=tot;  
        }  
    }g1,g2;  
    bool cmp(const data &u,const data &v){return u.z<v.z;}
    struct date{
        int x;ll d;
        bool operator <(const date b) const{return d>b.d;}
    };
    priority_queue <date> Q;
    void Dijkstra(){
        memset(dis,127,sizeof(dis));
        dis[1]=0;Q.push((date){1,0});
        while(!Q.empty()){
    	int x=Q.top().x;Q.pop();
    	if(vis[x])continue;vis[x]=1;
    	for(RG int i=g2.head[x];i;i=nxt[i]){
    	    int y=to[i];
    	    if(dis[y]>dis[x]+edg[i]){
    		dis[y]=dis[x]+edg[i],Q.push((date){y,dis[y]});
    	    }
    	}
        }
    }
    int main(){  
        scanf("%d%d",&n,&m);RG int i,j,x,y,z,p;  
        for(i=1;i<=m;i++){  
    	scanf("%d%d%d",&x,&y,&z);  
    	val[++cnt]=z; val[++cnt]=z;  
    	g1.lnk(x,cnt,cnt-1);g1.lnk(y,cnt-1,cnt);  
        }
        for(i=2;i<n;i++){  
    	for(p=g1.head[i],tmp=0; p; p=nxt[p])  
    	    a[++tmp]=(data){to[p],edg[p],val[to[p]]};  
    	if(!tot) continue;  
    	sort(a+1,a+tmp+1,cmp);  
    	for(j=1;j<=tmp;j++) g2.lnk(a[j].x,a[j].y,a[j].z);  
    	for(j=1;j<tmp;j++){  
    	    g2.lnk(a[j].y,a[j+1].y,a[j+1].z-a[j].z);  
    	    g2.lnk(a[j+1].y,a[j].y,0);  
    	}  
        }  
        T=++cnt;  
        for(p=g1.head[1];p;p=nxt[p]) g2.lnk(1,edg[p],val[edg[p]]);  
        for(p=g1.head[n];p;p=nxt[p]) g2.lnk(to[p],T,val[edg[p]]);  
        Dijkstra();printf("%lld
    ",dis[T]);
        return 0;  
    }  
    
  • 相关阅读:
    【Linux技术】常用的Linux系统调用
    【Linux技术】Windows与Linux系统下的库·初探
    【C/C++】嵌入式程序员应该知道的0X10个C语言问题
    【C/C++】struct探索·extern "C"含义探索 ·C++与C的混合编程·C 语言高效编程的几招
    【Acm】八皇后问题
    【驱动】linux设备驱动·扫盲
    【驱动】linux设备驱动·字符设备驱动开发
    【教程】ubuntu下配置nvc详细教程
    【教程】InstallShield使用完全教程
    【ARM】2410裸机系列-流水灯
  • 原文地址:https://www.cnblogs.com/qt666/p/7502473.html
Copyright © 2011-2022 走看看