[loj3560]From Hacks to Snitches

Posted by unklematt on Wed, 19 Jan 2022 16:37:14 +0100

Record $l_{x} $is the guard path length passing through $x $. If there is no such guard, $l will be defined_ {x}=1$

Note that if you can get to $x $at time $t $, you can obviously get there at time $t+l_{x} $reaches $x $(follow the direction of the guard), so define $d_{x,s} $is the earliest time to reach $x $and $\ equiv s (MOD \ L {x}) $, that is, it is monotonous, and it is not difficult to get the transfer as follows——

$$
d_{x,s}\rightarrow
d_{y,t}=\min_{k\in N,d_{x,s}+k\cdot l_{x}+1\equiv t(mod\ l_{y})}(d_{x,s}+k\cdot l_{x}+1)
$$
The transfer shall meet the following requirements: 1$ X = y $or $(x,y)\in E $; 2. No guard Passes $y $at time $t $; 3. There is no guard at $t $from $y $to $x $(note that $t $is equivalent to $d {x, s} + K \ cdot L {x} + 1 $)

In the above state transitions, the total number of transitions is $M=\sum_{(x,y)\in E}l_{x}l_{y}\le mL+L^{4} $(whether $X and Y $are guarded has been classified and discussed), and there is $d during transfer_ {x,s}<d_ {y, t} $, which can be implemented using dijkstra. The time complexity is $o(M\log M) $. It needs to be optimized

 

Specifically, the transfer is divided into four categories and optimized respectively:

1.$y $is not guarded. According to the monotonicity of dijkstra, for each $x $you only need to transfer this kind of $y $once

2. If $x $is not guarded and $y $is guarded, make $T $be $y $in $d_ The earliest time after {x, s} $is guarded is only transferred to $d_{x,s}+1 $and $T+1 $are enough

In addition, if $d_{x,s}+1=T $, then the former cannot be transferred. Note that the rest will be transferred within $y $

3.$(x,y) $is the side that a guard passes by (including positive order and negative order), which can be handled directly (note that only when $k=0 $)

4. In addition to the above, that is, $x,y $are guarded and not the side of a guard

Let $T $be $y $in $d_ If no guard Passes $x $after {x, s} $, you can wait on $y $and return $x $at time $T $(then return $y $)

In this way, all $D can be transferred_ {y, t} $, and has reached the lower limit (note dijkstra's greed), so it is similar to the second case. After the transfer, you can delete the edge

Further, if a guard passes through $x $at time $T $, the time before $T $can be transferred directly, otherwise it must go around several times until after time $T $

Record $T_{1} $is $T $and the earliest $\ equiv s (MOD \ L {x}) $after $T $(stop when going to $T {1} $), T_{2} $is $y $in $T_{1} $the earliest time after being guarded, similar judgment time $T_{2} $whether a guard Passes $x $: if no guard Passes $x $, the processing method is the same as that of $T $(but the edge is not deleted). Otherwise, it is not difficult to prove that it is meaningless to walk more circles through simple analysis

 

Considering the $M $at this time, the transfer is divided into three categories for analysis:

1. If a point in $X, y $is not guarded, such edges will only be transferred once, so the total number of transfers is $o(m)$

2.$(x,y) $is the edge that a guard passes by. This kind of edge has a total of $l $and is transferred at most $l $times, so the total number of transfers is $o(L^{2})$

3. In addition to the above case, that is, the fourth case in the optimization, consider the total number of transfers from $x $to ring $y $: the first transfer $ℓ_ {y} After $times, at most $\ lceil \ frac {ℓ {y} {L {x}} \ rceil $edges remain, that is, the remaining $L_ {x} - 1 $s $transfer times are only $\ lceil \ frac {ℓ {y} {L {x}} \ rceil $, and the sum is $ℓ_ {y}+(l_{x}-1)\lceil\frac{ℓ_{y}}{l_{x}}\rceil\le 2ℓ_ {y}$

Then sum up each point on the ring where $x $is located, and finally the total transfer number between the two rings is $o(ℓ {x} ℓ {y}) $, which is obviously $o(L^{2})$

To sum up, the total transfer amount of $M $is $o(m+L^{2}) $, and the time complexity is $o(M\log M) $, which can be passed

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 250005
  4 #define M 5000005
  5 struct Edge{
  6     int pre,nex,fr,to;
  7 }edge[M<<1];
  8 struct Data{
  9     int x,s,d;
 10     bool operator < (const Data &k)const{
 11         return d>k.d;
 12     }
 13 };
 14 priority_queue<Data>q;
 15 int n,m,t,E,x,y,ans,head[N],l[N],bl[N],pos[N],suml[N],vis0[N],vis[M],d[M];
 16 int read(){
 17     int x=0;
 18     char c=getchar();
 19     while ((c<'0')||(c>'9'))c=getchar();
 20     while ((c>='0')&&(c<='9')){
 21         x=x*10+c-'0';
 22         c=getchar();
 23     }
 24     return x;
 25 }
 26 int id(int x,int s){
 27     return suml[x-1]+s+1;
 28 }
 29 void upd(int x,int D){
 30     int s=D%l[x];
 31     if (d[id(x,s)]>D){
 32         d[id(x,s)]=D;
 33         q.push(Data{x,s,d[id(x,s)]});
 34     }
 35 }
 36 int get_nex(int d,int l,int s){
 37     if (d%l>s)d+=l-d%l;
 38     if (d%l<s)d+=s-d%l;
 39     return d;
 40 }
 41 void add(int x,int y){
 42     edge[E]=Edge{-1,head[x],x,y};
 43     if (head[x]!=-1)edge[head[x]].pre=E;
 44     head[x]=E++;
 45 }
 46 void del(int k){
 47     if (edge[k].nex>=0)edge[edge[k].nex].pre=edge[k].pre;
 48     if (edge[k].pre<0)head[edge[k].fr]=edge[k].nex;
 49     else edge[edge[k].pre].nex=edge[k].nex;
 50 }
 51 int calc(){
 52     memset(d,0x3f,sizeof(d));
 53     upd(1,0);
 54     while (!q.empty()){
 55         int x=q.top().x,s=q.top().s,D=q.top().d;
 56         q.pop();
 57         if (vis[id(x,s)])continue;
 58         vis[id(x,s)]=1;
 59         if ((!bl[x])||((s+1)%l[x]!=pos[x]))upd(x,D+1);
 60         for(int i=head[x];i!=-1;i=edge[i].nex){
 61             int y=edge[i].to,T=get_nex(D+1,l[y],pos[y]);
 62             if (!bl[y]){
 63                 upd(y,D+1),del(i);
 64                 continue;
 65             }
 66             if (!bl[x]){
 67                 if (D+1!=T)upd(y,D+1);
 68                 upd(y,T+1);
 69                 continue;
 70             }
 71             if ((bl[x]==bl[y])&&((pos[x]+1)%l[x]==pos[y])){
 72                 upd(y,D+1);
 73                 continue;
 74             }
 75             if ((bl[x]==bl[y])&&((pos[y]+1)%l[x]==pos[x])){
 76                 if ((s!=pos[y])&&((s+1)%l[x]!=pos[y]))upd(y,D+1);
 77                 continue;
 78             }
 79             if (D+1!=T)upd(y,D+1);
 80             if (T%l[x]!=pos[x]){
 81                 upd(y,T+1),del(i);
 82                 continue;
 83             }
 84             int T1=get_nex(T,l[x],s),T2=get_nex(T1+1,l[y],pos[y]);
 85             if (T1+1!=T2)upd(y,T1+1);
 86             if (T2%l[x]!=pos[x])upd(y,T2+1);
 87         }
 88     }
 89     return d[id(n,0)];
 90 }
 91 int main(){
 92     n=read(),m=read();
 93     memset(head,-1,sizeof(head));
 94     for(int i=1;i<=m;i++){
 95         x=read(),y=read();
 96         add(x,y),add(y,x);
 97     }
 98     t=read();
 99     for(int i=1;i<=n;i++)l[i]=1;
100     for(int i=1;i<=t;i++){
101         x=read();
102         for(int j=0;j<x;j++){
103             y=read();
104             l[y]=x,bl[y]=i,pos[y]=j;
105         }
106     }
107     for(int i=1;i<=n;i++)suml[i]=suml[i-1]+l[i];
108     ans=calc();
109     if (ans!=0x3f3f3f3f)printf("%d\n",ans);
110     else printf("impossible\n");
111     return 0;
112 }

 

Topics: LOJ