[Original question]
3040: Maximum short circuit (road) Time Limit: 60 Sec Memory Limit: 200 MB
Submit: 1036 Solved: 262
[Submit] [Status] Description
A directed graph of N points and M edges is used to calculate the shortest path of point 1 to point N (guaranteed to exist ).
1 <= N <= 000000,1 <= M <= 10000000
Input
The first line has two integers, N and M, indicating the number of points and the number of edges.
The second row contains six integers: T, rxa, rxc, rya, ryc, and rp.
The first T edge is generated as follows:
1. initialize x = y = z = 0.
2. Repeat the following process T times:
X = (x * rxa + rxc) % rp;
Y = (y * rya + ryc) % rp;
A = min (x % n + 1, y % n + 1 );
B = max (y % n + 1, y % n + 1 );
Then there is a directed edge from a to B with a length of 1e8-100 *.
Rear M-T side using read mode:
Next, three integers x, y, and z in each row of the M-T line indicate a directed edge with the length from x to y z.
1 <= x, y <= N, 0
Output
An integer ranging from 1 ~ N.
Sample Input3 3
0 1 2 3 5 7
1 2 1
1 3 3
2 3 1
Sample Output2
HINT
[Note]
Use efficient heap to optimize the Dijkstra algorithm.
Source
WC2013 camp member discussion-lydrainbowcat
[Analysis] It is a complete dijkstra heap optimization! However, this memory card is too tight. This is a miserable experience.
[NUM.1 -- System Heap] (changed to lld after handing in)
#include
#include
#include
#include
#include
//#include
//#include
using namespace std;typedef long long ll;typedef pair
Pair;const int N=1000005;const int M=10000005;ll x,y,z,rxa,rxc,rp,rya,ryc,aa,bb,dis[N],cnt;struct arr{int next,go,s;}a[M];int xx,yy,t,i,now,n,m,end[N],go;bool flag[N];priority_queue< Pair,vector
,greater
>q;void make_up(int u,int v,int w){ a[++cnt].go=v;a[cnt].s=w;a[cnt].next=end[u];end[u]=cnt;}int main(){ scanf(%d%d,&n,&m); scanf(%d%I64d%I64d%I64d%I64d%I64d,&t,&rxa,&rxc,&rya,&ryc,&rp); x=y=z=0; for (i=1;i<=t;i++) { x=(x*rxa+rxc)%rp;y=(y*rya+ryc)%rp; aa=min(x%n+1,y%n+1);bb=max(y%n+1,y%n+1); make_up((int)aa,(int)bb,100000000-100*aa); } for (i=1;i<=m-t;i++) { scanf(%d%d%d,&xx,&yy,&z); make_up(xx,yy,z); } memset(dis,60,sizeof(dis));dis[1]=0; q.push(pair
(dis[1],1)); while (!q.empty()) { Pair temp=q.top();q.pop(); now=temp.second; flag[now]=true; for (i=end[now];i;i=a[i].next) { go=a[i].go; if (dis[go]>dis[now]+ll(a[i].s)&&!flag[go]) { dis[go]=dis[now]+ll(a[i].s);q.push(make_pair(dis[go],go)); } } } printf(%I64d,dis[n]); return 0;}
But after running for about 5s, the memory burst ~~ RZZ said that this is because the dynamic queue burst into memory due to repeated heap operations.
[NUM2 -- manual heap]
#include
#include
#include
#include
using namespace std;typedef long long ll;typedef pair
Pair;const int N=1000005;const int M=10000005;ll x,y,rxa,rxc,rp,rya,ryc,aa,bb,dis[N],go,cnt,pre[N],end[N];Pair d[N*2];char ch;struct arr{int next,go,s;}a[M];bool flag[N];int xx,yy,z,t,i,now,n,m,len;void make_up(int u,int v,int w){ a[++cnt].go=v;a[cnt].s=w;a[cnt].next=end[u];end[u]=cnt;}void swap(Pair &a,Pair &b){ Pair c=a;a=b;b=c;}void pop(){ pre[d[1].second]=0;pre[d[len].second]=1;d[1]=d[len];len--; int now=1; while (true) { ll t1=d[now].first,t2=d[now*2].first,t3=d[now*2+1].first; if (t2
1) { pre[p]=now/2;pre[d[now/2].second]=now; swap(d[now],d[now/2]);now/=2; }}void push(Pair that){ d[++len]=that;int now=len,p=that.second;pre[p]=len; up(now,p);}int Read(){ while (ch<'0'||ch>'9') ch=getchar(); int s=0; while (ch>='0'&&ch<='9') s=s*10+ch-48,ch=getchar(); return s;}int main(){ scanf(%d%d,&n,&m); scanf(%d %lld %lld %lld %lld %lld,&t,&rxa,&rxc,&rya,&ryc,&rp); x=y=z=0; for (i=1;i<=t;i++) { x=(x*rxa+rxc)%rp;y=(y*rya+ryc)%rp; aa=min((ll)x%n+1,(ll)y%n+1);bb=max(ll(y%n+1),ll(y%n+1)); make_up((int)aa,(int)bb,(int)100000000-100*aa); } ch='!'; for (i=1;i<=m-t;i++) { xx=Read();yy=Read();z=Read(); make_up(xx,yy,z); } memset(dis,60,sizeof(dis)); memset(pre,0,sizeof(pre)); dis[1]=0;push(make_pair(dis[1],1));len=1;pre[1]=1; while (len) { Pair temp=d[1];pop(); now=temp.second;flag[now]=true; for (i=end[now];i;i=a[i].next) { go=a[i].go; if (dis[go]>dis[now]+ll(a[i].s)&&!flag[go]) { dis[go]=dis[now]+ll(a[i].s); if (pre[go]==0) push(make_pair(dis[go],go)); else { d[pre[go]].first=dis[go]; up(go,d[pre[go]].second); } } } } printf(%lld,dis[n]); return 0;}
The correctness of the manual Heap here is not guaranteed, because I don't write much about the heap. At the beginning, I added read optimization and opened a ing table to update the dis value already in the heap. Finally, we WA in 5s !!!
[Result] I heard that SYC has passed. Looking at his code carefully, it's a bit similar to my NUM.1 ~~ Take a closer look. He typed a wrong letter. A total of T edges are generated, but only N edges are generated !! So I changed t to n, and it passed ~~~~
[Positive solution] Of course, that is the behavior of card data !! It is said that the Fibonacci heap or system pair heap will be used. So I will study it later ~~