제출 #406163

#제출 시각아이디문제언어결과실행 시간메모리
406163errorgornFrom Hacks to Snitches (BOI21_watchmen)C++17
25 / 100
6047 ms159840 KiB
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define ii pair<int,int>
#define iii pair<int,ii>
#define fi first
#define se second
#define endl '\n'

#define puf push_front
#define pof pop_front
#define pub push_back
#define pob pop_back

#define rep(x,s,e) for (auto x=s-(s>e);x!=e-(s>e);(s<e)?x++:x--)
#define all(x) (x).begin(),(x).end()
#define sz(x) (int) (x).size()

int n,m,k;
vector<ii> edges;

vector<int> w[250005]; //period is implicit here
vector<int> al[250005];

int id[250005]; //which watchmen
int bad[250005]; //when the watchmen comes
int ped[250005];

vector<ii> dial[1000005];

void read(int &x){
	x=0;
	char ch=getchar_unlocked();
	while (ch&16){
		x=(x<<3)+(x<<1)+(ch&15);
		ch=getchar_unlocked();
	}
}

int fix(int i,int j){
	i%=j;
	if (i<0) i+=j;
	return i;
}

void upd(int k,int i,int j){
	if (w[i][j]>k){
		w[i][j]=k;
		//pq.push(iii(k,ii(i,j)));
		if (k>1000000) return;
		dial[k].pub(ii(i,j));
	}
}

int main(){
	cin.tie(0);
	cout.tie(0);
	cin.sync_with_stdio(false);
	
	read(n),read(m);
	
	int a,b;
	rep(x,0,m){
		read(a),read(b);
		al[a].pub(b);
		al[b].pub(a);
	}
	
	memset(ped,-1,sizeof(ped));
	memset(id,-1,sizeof(id));
	memset(bad,-1,sizeof(bad));
	
	read(k);
	rep(x,0,k){
		read(a);
		
		vector<int> path;
		rep(y,0,a){
			read(b);
			
			path.pub(b);
			bad[b]=y;
			id[b]=x;
			ped[b]=a;
		}
	}
	
	rep(x,1,n+1){
		if (ped[x]==-1) w[x].pub(1e9);
		else{
			rep(y,0,ped[x]) w[x].pub(1e9);
		}
	}
	
	upd(0,1,0);
	
	int weight=0;
	while (weight<1000000){
		if (dial[weight].empty()){
			weight++;
			continue;
		}
		
		int n1,n2;
		tie(n1,n2)=dial[weight].back();
		dial[weight].pob();
		
		if (w[n1][n2]!=weight) continue;
		if (ped[n1]!=-1 && weight%ped[n1]==bad[n1]) continue;
		//same position as watchmen
		
		if (n1==n){
			cout<<weight<<endl;
			return 0;
		}
		
		//cout<<weight<<" "<<n1<<" "<<n2<<" "<<ped[n1]<<" "<<bad[n1]<<endl;
		
		for (int x=0;x<sz(al[n1]);x++){
			auto it=al[n1][x];
			
			if (ped[it]==-1){
				//normal dijkstra into node without period
				int ww=weight;
				if (n1<=n) ww++;
				upd(ww,it,0);
				
				//delete the edge
				swap(al[n1][x],al[n1].back());
				al[n1].pob();
				x--;
			}
			else if (ped[n1]==-1 && ped[it]!=-1){
				//node without period into node with period
				int ww=weight+1;
				upd(ww,it,ww%ped[it]);
				
				//also need one that lands immediately after watchmen pass
				ww=weight+fix(bad[it]-weight,ped[it])+1;
				upd(ww,it,ww%ped[it]);
			}
			else if (id[n1]==id[it]){
				//same watchmen
				int ww=weight+1;
				
				if ((bad[it]+1)%ped[it]==bad[n1] && ww%ped[it]==bad[n1]) continue;
				upd(ww,it,ww%ped[it]);
			}
			else{
				//different watchmen
				
				//time that watchmen on other side steps on it
				int tt=weight+fix(bad[it]-weight,ped[it]);
				
				if (tt%ped[n1]==bad[n1]){ //cannot come back to our side
					upd(weight+1,it,weight%ped[it]);
					upd(weight+1+ped[n1],it,(weight+1+ped[n1])%ped[it]);
					
					tt=(weight+ped[n1])+fix(bad[it]-(weight+ped[n1]),ped[it]);
					if (tt%ped[n1]!=bad[n1]) upd(tt+1,it,(tt+1)%ped[it]);
				}
				else{ //ok we can update all it
					upd(weight+1,it,weight%ped[it]);
					upd(tt+1,it,(tt+1)%ped[it]);
					
					//delete the edge
					swap(al[n1][x],al[n1].back());
					al[n1].pob();
					x--;
				}
			}
		}
		
		if (ped[n1]!=-1){
			upd(weight+1,n1,(n2+1)%ped[n1]);
		}
	}
	
	
	/*
	rep(x,1,IDX){
		cout<<x<<": ";
		for (auto &it:w[x]) cout<<it<<" "; cout<<endl;
	}
	//*/
	
	cout<<"impossible"<<endl;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...