此思路是否正确
查看原帖
此思路是否正确
741839
arrowpoint楼主2024/9/18 19:46

我看到这题后感觉可以建立反向图,遍历所有无速度的边,对无速度边起点反图能到达的所有点连接上无速度边终点,速度就是反图中边的速度,长度是无速度边和有速度边之和,以此消掉所有有速度边后跑dij,但是连样例都过不了,很怀疑这种思路的正确性。

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;

const int N = 10005;
int n,m,a[N];
int d;
int edge[N][2],leng[N],idx;
bool vis[N],divis[N];
double dis[N];
int last[N];

struct node{
	int v,s,l,tag;
};
struct com{
	int v;
	double dis;
	bool operator < (const com &a) const{
		return dis>a.dis;
	}
};
vector<node> vec[N],g[N];

inline void dfs(int x){
	if(vis[x]) return;
	int u = edge[x][0],to = edge[x][1];
	vis[x] = 1;
	for(int i=0;i<g[u].size();i++){
		if(g[u][i].tag){
			dfs(g[u][i].tag);
			continue;
		}
		int v = g[u][i].v;
		vec[v].push_back({to,g[u][i].s,g[u][i].l+leng[x],0});
		g[to].push_back({v,g[u][i].s,g[u][i].l+leng[x],0});
	}
}

inline void dij(int s){
	priority_queue<com> q;
	for(int i=0;i<=n;i++){
		dis[i] = 1e16;
	}
	dis[s] = 0;
	q.push({s,0});
	while(!q.empty()){
		int u = q.top().v;
		q.pop();
		if(divis[u]) continue;
		divis[u] = 1;
		for(auto ed:vec[u]){
			if(ed.tag) continue;
			double w = double(ed.l)/ed.s;
			//cout<<ed.l<<' '<<ed.s<<endl;
			if(dis[ed.v] > dis[u] + w){
				dis[ed.v] = dis[u] + w;
				last[ed.v] = u;
				q.push({ed.v,dis[ed.v]});
			}
		}
	}
}

inline void print(int x){
	if(x) print(last[x]);
	cout<<x<<" ";
}

signed main(){
	ios::sync_with_stdio(false);
	cin>>n>>m>>d;
	int q1,q2,q3,q4;
	for(int i=1;i<=m;i++){
		cin>>q1>>q2>>q3>>q4;
		if(q3==0 && q1==0){
			q3 = 70;
		}
		if(q3==0){
			edge[++idx][0] = q1,edge[++idx][1] = q2;
			leng[idx] = q4;
			vec[q1].push_back({q2,-1,q4,idx});
			g[q2].push_back({q1,-1,q4,idx});
		}
		else{
			vec[q1].push_back({q2,q3,q4,0});
			g[q2].push_back({q1,q3,q4,1});
		}
	}
	for(int i=1;i<=idx;i++){
		if(!vis[i]) dfs(i);
	}
	dij(0);
	print(d);
	
	return 0;
}
2024/9/18 19:46
加载中...