2024年第七届传智杯程序设计挑战赛复赛(第一场):小苯的网络配置(A组、B组、C组)

原题链接:E-小苯的网络配置(A组、B组、C组)_2024年第七届传智杯程序设计挑战赛复赛(第一场)

解题思路:最短路问题用Dijksta算法,这题的难点在于传输记录,怎么确定当前路径就是最短路,并且记录每条分支是不是最短路。观察得到对于每条边 (u,v),如果此边在某条最短路上的话,则一定满足 dist(1,u)+dist(v,n)+w[u,v]=dist(1,n),即最短路从 1 到 u,再从 u 到 v,再从 v 到 n。或者将 u,v 反过来的这个条件也成立。因此我们先预处理从 1 出发的 dijkstra,再预处理一个 从n出发的 dijkstra,求出 n 到所有点的最短路记作 dn。接着只需要枚举每条边 (u,v),进行 check 即可。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+10;
typedef pair<long long,int> PII;
long long e[N],ne[N],idx,h[N],w[N];
//dist[0]记录从1—n的最短路,dist[1]记录从n-1的最短路 
long long dist[2][N];
long long edge[3][N];	
int n,m;
//创建邻接表 
void add(int a,int b,long long c){
	e[idx]=b;
	w[idx]=c;
	ne[idx]=h[a];
	h[a]=idx++;
}
//进行check 
bool check(long long a,long long b,long long c){
	return dist[0][a]+dist[1][b]+c==dist[0][n];
}
// Dijkstra算法 
void Dijkstra(int s,long long  dist[]){
	bool st[N];
	for(int i = 0; i <= n; i++) 
	dist[i] = 2e18, st[i] = 0;
	dist[s]=0;
	priority_queue<PII,vector<PII>,greater<PII>> heap;
	heap.push({0,s});
	while(heap.size()){
		auto t=heap.top().second;
		heap.pop();
		if(st[t])continue;
		st[t]=true;
		for(int i=h[t];i!=-1;i=ne[i]){
			int j=e[i];
			if(dist[j]>dist[t]+w[i]){
				dist[j]=dist[t]+w[i];
				heap.push({dist[j],j});
			}
		}
	}
}
void solve(){
	cin>>n>>m;
	memset(h,-1,sizeof h);
	for(int i=1;i<=m;i++){
		int a,b,c;
		cin>>a>>b>>c;
		add(a,b,c);
		add(b,a,c);
		//保存节点 
		edge[0][i]=a;
		edge[1][i]=b;
		edge[2][i]=c;
	}
	//预处理最短路 
	Dijkstra(1,dist[0]);
	Dijkstra(n,dist[1]);
	//检查 
	for(int i=1;i<=m;i++){
		long long a=edge[0][i],b=edge[1][i],c=edge[2][i];
		if(check(a,b,c)||check(b,a,c))cout<<1;
		else cout<<0;
	}
	cout<<endl;
}
int main(){
	int t;
	cin>>t;
	while(t--){
		solve();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值