Educational Codeforces Round 51 (Rated for Div. 2)F. The Shortest Statement(技巧+最短路)

原题传送门

题意

  给出一个边比点数多至多20条的无向连通图,每条边有一个边权,多次询问两点间最短路。

分析

  首先我们选出其中n-1条边建出一颗树,然后将多余的m-n+1条边的两个端点取出来,对所有点跑最短路,由于 m − n ≤ 20 m-n\leq20 mn20,那么我们取出的点最多不会超过 2 ∗ ( m − n + 1 ) ≤ 42 2*(m-n+1)\leq42 2(mn+1)42个,我们可以使用Floyd或dijkstra甚至spfa来求最短路。然后对于每次询问,我们枚举每个取出来的点,然后将这个点与两个询问点的最短路加起来然后和树上这两点距离取min就是答案了,总复杂度 O ( 40 ∗ n ∗ log ⁡ m + 40 ∗ q ) O(40*n*\log m+40*q) O(40nlogm+40q)

Code

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
/*================Header Template==============*/
const int maxn=100500;
const long long inf=1e15;
vector<int>P,vis,F[maxn];
int n,m,exi[maxn],gra[18][maxn],dep[maxn];
ll sum[maxn],dis[45][maxn],len[maxn];
struct Edge {
	int u,v,w;
	Edge(int u=0,int v=0,int w=0):u(u),v(v),w(w){}
};
vector<Edge>edges;
inline void addedge(int u,int v,int w) {
	edges.push_back(Edge(u,v,w));
	edges.push_back(Edge(v,u,w));
	vis.push_back(0),vis.push_back(0);
	F[u].push_back(edges.size()-2);
	F[v].push_back(edges.size()-1); 
}
inline void dfs(int u,int f) {
	gra[0][u]=f;
	for(int i=1;i<18;++i)
		gra[i][u]=gra[i-1][gra[i-1][u]];
	for(int i=0;i<(int)F[u].size();++i) {
		int p=F[u][i];
		Edge &e=edges[p];
		int v=e.v;
		if(v==f)
			continue;
//		cout<<u<<" -> "<<v<<" "<<exi[v]<<endl;
		if(exi[v])
			continue;
		exi[v]=1;
		vis[p]=vis[p^1]=1;
		len[v]=len[u]+e.w;
		dep[v]=dep[u]+1;
		dfs(v,u);
	}
}
inline int lca(int x,int y) {
	if(dep[x]<dep[y])
		swap(x,y);
	for(int d=dep[x]-dep[y],i=17;~i;--i)
		if(d>>i&1)
			x=gra[i][x];
	if(x==y)
		return x;
	for(int i=17;~i;--i)
		if(gra[i][x]!=gra[i][y])
			x=gra[i][x],y=gra[i][y];
	return gra[0][x];
}
struct node {
	ll d;
	int u;
	node(ll d=0,int u=0):d(d),u(u){}
	inline bool operator < (const node &rhs) const {
		return u>rhs.u;
	}
};
inline void spfa(int S) {
    for(int i=1;i<=n;i++)
		dis[S][i]=inf;
	priority_queue<node>q;
    int val=P[S];
    dis[S][val]=0;
    q.push(node(0,val));
    while(!q.empty()) {
        int u=q.top().u;q.pop();
        for(int i=0;i<(int)F[u].size();i++) {
        	Edge &e=edges[F[u][i]];
            int v=e.v,cost=e.w;
            if(dis[S][v]>dis[S][u]+cost)
                dis[S][v]=dis[S][u]+cost,q.push(node(dis[S][v],v));
        }
    }
}
int main() {
	read(n),read(m);
    for(int i=1,a,b,c;i<=m;i++)
    	read(a),read(b),read(c),addedge(a,b,c);
    exi[1]=1;
    dfs(1,0);
    for(int i=0,a,b;i<(int)vis.size();i+=2) {
//    	cout<<i<<" "<<vis[i]<<endl;
    	if(vis[i])
    		continue;
    	a=edges[i].u,b=edges[i].v;
        P.push_back(a);
        P.push_back(b);
	}
//	for(int i=0;i<(int)P.size();++i)
//		cout<<P[i]<<" ";
//	cout<<endl;
    sort(P.begin(),P.end());
    P.resize(unique(P.begin(),P.end())-P.begin());
 	for(int i=0;i<(int)P.size();i++)
		spfa(i);
    int q,a,b;
	read(q);
    while(q--) {
    	read(a),read(b);
    	int l=lca(a,b);
    	ll ans=len[a]+len[b]-len[l]*2;
        for(int i=0;i<(int)P.size();i++)
            ans=min(ans,dis[i][a]+dis[i][b]);
        printf("%lld\n",ans);
    }
}
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值