zoukankan      html  css  js  c++  java
  • [BZOJ4289][PA2012]TAX(最短路)

    首先考虑一种暴力做法,为每条边拆成两条有向边,各建一个点。若某两条边有公共点,则在边所对应的点之间连一条边,权值为两条边中的较大值。这样跑最短路是$O(m^2log m)$的。

    用类似网络流中补流的方法,一条边拆成的两个点之间连权值为边的原权值的边(第一种边)。对于一个点,将所有以它为起点的边排序,将相邻的两条边对应的点连边,小的往大的连权值为两条边的原权值差的边,大的往小的连权值为0的边(第二种边)。建超级源汇,最短路即可。

    若流了第一种边则代表最短路中有这条边,若流了第二种边则代表换边。复杂度$O(mlog m)$

     1 #include<queue>
     2 #include<vector>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<algorithm>
     6 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     7 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
     8 typedef long long ll;
     9 using namespace std;
    10 
    11 const int N=1200010;
    12 const ll inf=1e15;
    13 ll dis[N];
    14 bool b[N];
    15 int n,m,u,v,w,cnt,nd,q[N],h[N],to[N],nxt[N],val[N];
    16 struct E{ int u,v,w; }a[N];
    17 vector<int>V[N];
    18 bool cmp(int x,int y){ return a[x].w<a[y].w; }
    19 struct P{ int x; ll d; };
    20 bool operator <(const P &a,const P &b){ return a.d>b.d; }
    21 priority_queue<P>Q;
    22 void add(int u,int v,int w){ to[++nd]=v; val[nd]=w; nxt[nd]=h[u]; h[u]=nd; }
    23 
    24 int main(){
    25     scanf("%d%d",&n,&m);
    26     rep(i,1,m){
    27         scanf("%d%d%d",&u,&v,&w);
    28         a[++cnt]=(E){u,v,w}; a[++cnt]=(E){v,u,w};
    29         add(cnt,cnt-1,w); add(cnt-1,cnt,w);
    30         V[u].push_back(cnt-1); V[v].push_back(cnt);
    31     }
    32     rep(i,1,n){
    33         int tot=0;
    34         rep(j,0,(int)V[i].size()-1) q[++tot]=V[i][j];
    35         if (!tot) continue;
    36         sort(q+1,q+tot+1,cmp);
    37         rep(j,1,tot-1) add(q[j],q[j+1],a[q[j+1]].w-a[q[j]].w),add(q[j+1],q[j],0);
    38     }
    39     int S=cnt+1,T=cnt+2;
    40     rep(i,1,cnt){
    41         if (a[i].u==1) add(S,i,a[i].w);
    42         if (a[i].v==n) add(i,T,a[i].w);
    43     }
    44     rep(i,1,T) dis[i]=inf; Q.push((P){S,0}); dis[S]=0;
    45     while (!Q.empty()){
    46         int x=Q.top().x; Q.pop();
    47         if (b[x]) continue;
    48         b[x]=1;
    49         For(i,x) if (dis[k=to[i]]>dis[x]+val[i])
    50             dis[k]=dis[x]+val[i],Q.push((P){k,dis[k]});
    51     }
    52     printf("%lld
    ",dis[T]);
    53     return 0;
    54 }
  • 相关阅读:
    Gradle在大型Java项目上的应用
    2015年,移动开发都有哪些热点?
    为什么寄存器比内存快?
    Gogs:可能是比Gitlab更好的选择
    自定义元素–为你的HTML代码定义新元素
    在DLL编程中,导出函数为什么需要extern "C"
    c调用c++编的dll,c++调用c编写的dll,extern “C”的用法
    C/C++:函数的编译方式与调用约定以及extern “C”的使用
    在VS2015中用C++编写可被其它语言调用的动态库DLL
    C++在VS下创建、调用dll
  • 原文地址:https://www.cnblogs.com/HocRiser/p/9894930.html
Copyright © 2011-2022 走看看