BZOJ 4289: PA2012 Tax 差分建图 最短路

https://www.lydsy.com/JudgeOnline/problem.php?id=4289

https://www.cnblogs.com/clrs97/p/5046933.html  claris的题解很清晰

 

如果单纯把无向边拆成有向边然后变成点再连有向边需要建m^2条边。

那么这里可以差分建图压缩新图边的数量,把原图每个点的出边和入边排序,权值相同的出边到入边(开始是无向图所以每个出边一定有权值相同的入边,入边也是)连一条权值为相同权值的边。

(从小到大排序后)每条出边往它的前一条边连一条权值为0的边,向后一条边连一条权值为 (后一条边权值)-(当前边权值) 的边。

最后设置一个总入点和总出点相应连1的出边和n的入边就可以了。

合理性就不再说了。

 

空间要注意,这道题空间开小了wa开大了tle。卡了半天......

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 #define LL long long
 9 #define pa pair<LL,int>
10 const int maxn=210000;
11 int n,m;
12 struct node{ int x,y;LL v; }a[maxn*2],b[maxn*2];int cnt=0;
13 struct nod1{ int y,z,next; }e1[maxn*2];
14 struct nod{ int y,next;LL v;}e[maxn*10];
15 int head1[maxn]={},head[maxn*2]={},tot1=0,tot=0;
16 priority_queue< pa ,vector< pa > , greater< pa > >q;
17 int S,T; LL dis[maxn*2]={};
18 inline void init1(int x,int y,int z){e1[++tot1].y=y;e1[tot1].z=z;e1[tot1].next=head1[x];head1[x]=tot1;}
19 inline void init(int x,int y,LL v){e[++tot].y=y;e[tot].v=v;e[tot].next=head[x];head[x]=tot;}
20 bool mcmp(node aa,node bb){return aa.v<bb.v;}
21 void Dij(){
22     memset(dis,63,sizeof(dis));
23     dis[S]=0;q.push(make_pair(dis[S],S));
24     while(!q.empty()){
25         LL v=q.top().first;int x=q.top().second;q.pop();
26         if(v>dis[x])continue;
27         for(int i=head[x];i;i=e[i].next){
28             if(dis[e[i].y]>dis[x]+e[i].v){
29                 dis[e[i].y]=dis[x]+e[i].v;
30                 q.push(make_pair(dis[e[i].y],e[i].y));
31             }
32         }
33     }
34 }
35 int main(){
36     scanf("%d%d",&n,&m);
37     int x,y;LL z;
38     for(int i=1;i<=m;i++){
39         scanf("%d%d%lld",&x,&y,&z);
40         a[++cnt].x=x;a[cnt].y=y;a[cnt].v=z;
41         a[++cnt].x=y;a[cnt].y=x;a[cnt].v=z;
42         init1(x,cnt,cnt-1);init1(y,cnt-1,cnt);//入边 出边
43     }
44     S=cnt+1;T=S+1;
45     for(int i=1;i<=n;i++){
46         int zz=0;
47         for(int j=head1[i];j;j=e1[j].next){
48             b[++zz].x=e1[j].y; b[zz].y=e1[j].z; b[zz].v=a[e1[j].y].v;
49         }
50         sort(b+1,b+1+zz,mcmp);
51         for(int j=1;j<=zz;j++)init(b[j].x,b[j].y,b[j].v);
52         for(int j=1;j<zz;j++){init(b[j+1].y,b[j].y,0); init(b[j].y,b[j+1].y,b[j+1].v-b[j].v);}
53     }
54     for(int i=1;i<=cnt;i++){
55         if(a[i].y==n)init(i,T,a[i].v);
56         if(a[i].x==1)init(S,i,a[i].v);
57     }
58     Dij();
59     printf("%lld\n",dis[T]);
60     return 0;
61 }
View Code

 

posted @ 2018-04-18 12:29  鲸头鹳  阅读(158)  评论(0编辑  收藏  举报