Submission #205361

#TimeUsernameProblemLanguageResultExecution timeMemory
205361TadijaSebezOlympic Bus (JOI20_ho_t4)C++11
100 / 100
396 ms4856 KiB
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
const int N=205;
const int M=50050;
const int inf=2e9+7;
struct Edge{int u,v,c,d;};
Edge edges[M];
bool bridge[M];
struct Bridges{
	static const int NSZ=205;
	vector<pair<int,int>> E[NSZ];
	vector<int> ans;
	int n,disc[NSZ],low[NSZ],tid;
	void init(int _n){n=_n;tid=0;ans.clear();for(int i=1;i<=n;i++)E[i].clear(),disc[i]=low[i]=0;}
	void AddEdge(int u,int v,int e){E[u].pb({v,e});E[v].pb({u,e});}
	void DFS(int u,int p){
		disc[u]=low[u]=++tid;
		for(auto e:E[u])if(e.second!=p){
			int v=e.first;
			if(!disc[v]){
				DFS(v,e.second);
				if(low[v]>disc[u])ans.pb(e.second);
				low[u]=min(low[u],low[v]);
			}else low[u]=min(low[u],disc[v]);
		}
	}
}GPH;
void FindBridges(vector<pair<int,int>> go[],int st,int n){
	GPH.init(n);
	vector<bool> was(n+1,0);
	function<void(int)> CNS=[&](int u){
		was[u]=1;
		for(auto e:go[u]){
			GPH.AddEdge(u,e.first,e.second);
			if(!was[e.first])CNS(e.first);
		}
	};
	CNS(st);
	GPH.DFS(st,-1);
	//printf(":D\n");
	for(int i:GPH.ans)bridge[i]=1;
}
struct DijkstraPQ{
	static const int N=205;
	int a[N],idx[N],val[N],n;
	void init(int _n,int st,int inf){
		n=_n;
		for(int i=1;i<=n;i++)a[i]=i,val[i]=inf;
		swap(a[st],a[1]);
		for(int i=1;i<=n;i++)idx[a[i]]=i;
		val[st]=0;
	}
	int size(){return n;}
	void Change(int x,int f){
		val[x]=f;
		int p=idx[x];
		while(p>1 && f<val[a[p/2]])a[p]=a[p/2],idx[a[p]]=p,p/=2;
		a[p]=x;idx[x]=p;
	}
	int top(){return a[1];}
	void pop(){
		int now=1;
		a[1]=a[n];n--;
		idx[a[1]]=1;
		while(now*2<=n){
			int ch=now*2;
			if(ch+1<=n && val[a[ch+1]]<val[a[ch]])ch++;
			if(val[a[now]]<=val[a[ch]])break;
			swap(a[now],a[ch]);
			idx[a[now]]=now;
			idx[a[ch]]=ch;
			now=ch;
		}
	}
};
void Dijkstra(vector<pair<int,int>> E[],int n,int st,int dist[],vector<pair<int,int>> go[]){
	for(int i=1;i<=n;i++)dist[i]=inf,go[i].clear();
	DijkstraPQ pq;pq.init(n,st,inf);
	dist[st]=0;
	while(pq.size()){
		int u=pq.top();
		pq.pop();
		for(auto e:E[u]){
			int v=e.first,w=edges[e.second].c;
			if(dist[v]>dist[u]+w){
				dist[v]=dist[u]+w;
				go[v].clear();
				//pq.push({-dist[v],v});
				pq.Change(v,dist[v]);
			}
			if(dist[v]==dist[u]+w)go[v].pb({u,e.second});
		}
	}
}
vector<pair<int,int>> E[N],R[N],T[N],go[N];
void BuildRev(int j,int m,int n){
	for(int i=1;i<=n;i++)T[i].clear();
	for(int i=1;i<=m;i++){
		if(i!=j)T[edges[i].u].pb({edges[i].v,i});
		else T[edges[i].v].pb({edges[i].u,i});
	}
}
int dist[2][2][N],tmp[N];
int main(){
	int n,m;
	scanf("%i %i",&n,&m);
	for(int i=1;i<=m;i++){
		scanf("%i %i %i %i",&edges[i].u,&edges[i].v,&edges[i].c,&edges[i].d);
		E[edges[i].u].pb({edges[i].v,i});
		R[edges[i].v].pb({edges[i].u,i});
	}
	Dijkstra(E,n,1,dist[0][0],go);
	FindBridges(go,n,n);
	Dijkstra(R,n,n,dist[0][1],go);
	Dijkstra(E,n,n,dist[1][0],go);
	FindBridges(go,1,n);
	Dijkstra(R,n,1,dist[1][1],go);
	ll ans=(ll)dist[0][0][n]+dist[1][0][1];
	for(int i=1;i<=m;i++){
		if(bridge[i]){
			BuildRev(i,m,n);
			Dijkstra(T,n,1,tmp,go);
			ll now=tmp[n];
			if(now==inf)continue;
			//printf("%i ",tmp[n]);
			Dijkstra(T,n,n,tmp,go);
			now+=tmp[1];
			//printf("%i ",tmp[1]);
			now+=edges[i].d;
			ans=min(ans,now);
			//printf("%i %lld\n",i,now);
		}else{
			int u=edges[i].u,v=edges[i].v,c=edges[i].c,d=edges[i].d;
			ll d1=dist[0][0][n];
			if(dist[0][0][v]<dist[0][0][u])d1=min(d1,(ll)dist[0][0][v]+c+dist[0][1][u]);
			ll d2=dist[1][0][1];
			if(dist[1][0][v]<dist[1][0][u])d2=min(d2,(ll)dist[1][0][v]+c+dist[1][1][u]);
			ans=min(ans,d1+d2+d);
		}
	}
	if(ans<inf)printf("%lld\n",ans);
	else printf("-1\n");
	return 0;
}

Compilation message (stderr)

ho_t4.cpp: In function 'int main()':
ho_t4.cpp:108:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%i %i",&n,&m);
  ~~~~~^~~~~~~~~~~~~~~
ho_t4.cpp:110:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%i %i %i %i",&edges[i].u,&edges[i].v,&edges[i].c,&edges[i].d);
   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...