codeforces上第15个点没过
查看原帖
codeforces上第15个点没过
30148
AXXWTGST楼主2023/12/17 09:06

我的思路大概是先跑一遍最短路(不考虑所有0的边),如果比L还小自然不行。 然后第二次最短路将每个0的边当作1考虑,如果能到达并且小于等于L的话必然可以,同时记录下来最短路径(方便后续更新边上的值),更新完值之后剩下的还为0的边全部赋一个比L大的值就可以了

代码里一些不太好的习惯别太在意


#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
struct edge {
	int from;
	int to;
	int val;
	int next;
};
const int maxn = 1005;
const int maxm = 2e5 + 10;
edge E[maxm];
int last[maxn];
int id = 0;
int n,m,L,s,t;
int dis[maxn];
int erased[maxn];
int arrive[maxn];
queue<int> Q;
void build(int st, int ed, int val) {
	id ++;
	E[id].from = st;
	E[id].to = ed;
	E[id].val = val;
	E[id].next = last[st];
	last[st] = id;
}
int main() {
	cin >> n >> m >> L >> s >> t;
	for(int i = 1;i <= m;i++)
	{
		int x,y,z;
		cin >> x >> y >> z;
		build(x,y,z);
		build(y,x,z);	
	}
	memset(dis,-1,sizeof(dis));
	dis[s] = 0;
	Q.push(s);
	while(!Q.empty()) {
		int pos = Q.front();
		Q.pop();
		for(int i = last[pos];i != 0;i = E[i].next) {
			if(E[i].val != 0) {
				if(dis[E[i].to] == -1 || dis[E[i].to] > dis[pos] + E[i].val) {
					dis[E[i].to] = dis[pos] + E[i].val;
					Q.push(E[i].to); 
				}
			}
		}
	}
	int temp = dis[t];
	if(temp != -1 && temp < L)
	{
		cout << "NO" << endl;
		return 0;	
	}
	memset(dis,-1,sizeof(dis));
	memset(erased,0,sizeof(erased));
	memset(arrive,0,sizeof(arrive));
	Q.push(s);
	dis[s] = 0;
	while(!Q.empty()) {
		int pos = Q.front();
		Q.pop();
		for(int i = last[pos];i != 0;i = E[i].next) {
			if(E[i].val == 0) {
				if(dis[E[i].to] == -1 || dis[E[i].to] + erased[E[i].to] > dis[pos] + erased[pos] + 1)
				{
					dis[E[i].to] = dis[pos];
					erased[E[i].to] = erased[pos] + 1;
					arrive[E[i].to] = i;
					Q.push(E[i].to); 
				}
			}
			else {
				if(dis[E[i].to] == -1 || dis[E[i].to] + erased[E[i].to] > dis[pos] + erased[pos] + E[i].val)
				{
					dis[E[i].to] = dis[pos] + E[i].val;
					erased[E[i].to] = erased[pos];
					arrive[E[i].to] = i;
					Q.push(E[i].to); 
				}
			}
		}
	}
	if(dis[t] == -1 || dis[t] + erased[t] > L) {
		cout <<"NO"<<endl;
		return 0;
	}
	bool up = false;
	int pos = t;
	int prev;
	bool pd[maxn];
	memset(pd,false,sizeof(pd));
	while(pos != s) {
		prev = E[arrive[pos]].from;
		if(E[arrive[pos]].val == 0) {
			if(up) {
				E[arrive[pos]].val = 1;
				if(arrive[pos] % 2 == 0)
					E[arrive[pos] - 1].val = 1;
			}	
			if(!up) {
				E[arrive[pos]].val = L - dis[t] - erased[t] + 1;
				if(arrive[pos] % 2 == 0)
					E[arrive[pos] - 1].val = L - dis[t] - erased[t] + 1;
				up = true;
			}
		}
		if(pd[pos] == true)
			cout <<"A "<< pos << endl;
		pd[pos] = true;
		pos = prev;
	}
	cout <<"YES"<<endl;
	for(int i = 1;i <= id;i += 2)
	{
		if(E[i].val == 0)
			E[i].val = L + 1;
		cout << E[i].from << " " << E[i].to << " " << E[i].val <<endl;
	}
	return 0;
}

我大概测试了一下,tle的原因是因为在while里面,沿着最优路径一路往回寻找的时候形成了一个循环,然后我看半天代码没觉出任何出现循环的可能。

2023/12/17 09:06
加载中...