• BZOJ4289 : PA2012 Tax


    一个直观的想法是把每条边拆成两条有向边,同时每条有向边是新图中的一个点。对于两条边a->b与b->c,两点之间连有向边,费用为两条边费用的最大值。然后新建源点S与汇点T,由S向所有起点为1的边连边,T接受所有终点为n的边,那么答案就是S到T的最短路。

    这样子的边数为$O(m^2)$,不能承受。

    考虑枚举中转点x,将所有与它有关的边按费用从小到大排序。对于每条边,从以x为终点的点向以x为起点的点连边,费用为该边的费用。从以x为起点的点向下一条边连边,费用为两条边费用的差值,向上一条边连边,费用为0。

    这样子建图,边数为$O(m)$,可以承受。

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    typedef long long ll;
    typedef pair<int,ll> PI;
    const int N=100010,M=200010;
    int n,m,i,j,x,y,z,cnt,t,S,T;
    int g[N],en[M<<1],st[M<<1],nxt[M<<1],ed;
    int G[M<<1],V[M*6],W[M*6],NXT[M*6],ED;
    ll d[M<<1];
    priority_queue<PI,vector<PI>,greater<PI> >Q;
    struct P{int x,y,z;P(){}P(int _x,int _y,int _z){x=_x,y=_y,z=_z;}}a[M<<1],q[M];
    inline bool cmp(const P&a,const P&b){return a.z<b.z;}
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline void addedge(int x,int y,int z){en[++ed]=y;st[ed]=z;nxt[ed]=g[x];g[x]=ed;}
    inline void add(int x,int y,int z){V[++ED]=y;W[ED]=z;NXT[ED]=G[x];G[x]=ED;}
    int main(){
      read(n),read(m);
      while(m--){
        read(x),read(y),read(z);
        a[++cnt]=P(x,y,z);
        a[++cnt]=P(y,x,z);
        addedge(x,cnt,cnt-1);
        addedge(y,cnt-1,cnt);
      }
      for(i=1;i<=n;i++){
        for(t=0,j=g[i];j;j=nxt[j])q[++t]=P(en[j],st[j],a[en[j]].z);
        if(!t)continue;
        sort(q+1,q+t+1,cmp);
        for(j=1;j<=t;j++)add(q[j].x,q[j].y,q[j].z);
        for(j=1;j<t;j++){
          add(q[j].y,q[j+1].y,q[j+1].z-q[j].z);
          add(q[j+1].y,q[j].y,0);
        }
      }
      S=cnt+1;T=S+1;
      for(i=1;i<=cnt;i++){
        if(a[i].x==1)add(S,i,a[i].z);
        if(a[i].y==n)add(i,T,a[i].z);
      }
      for(i=1;i<=T;i++)d[i]=1LL<<60;
      Q.push(PI(d[S]=0,S));
      while(!Q.empty()){
        PI t=Q.top();Q.pop();
        if(d[x=t.second]<t.first)continue;
        for(i=G[x];i;i=NXT[i])if(d[x]+W[i]<d[V[i]])Q.push(PI(d[V[i]]=d[x]+W[i],V[i]));
      }
      return printf("%lld",d[T]),0;
    }
    

      

  • 相关阅读:
    IDEA下同时使用Git和svn
    IDEA进行activiti-archetype-unittest脚手架的安装
    正则表达式
    关于JS堆栈与拷贝
    按值传递--
    JS---变量、作用域和内存问题
    laod
    待解决
    闭包2
    闭包1
  • 原文地址:https://www.cnblogs.com/clrs97/p/5046933.html
Copyright © 2020-2023  润新知