codeforces 59E shortest path

今天终于做出了一道困扰我一学期的题,就是这道shortestpath。其要求不能连续访问某些三个城市,比如限制1 2 3, 则不能在访问完1、2后访问3.一种直白的想法(从同班同学黄毅飞那里听来的)就是以边建图,同时可以增加一个起始城市0连一条0->1的单行道,再连一条n->n+1的单行道,从而转换为0到n+1的dijkstra(但是后来发现dijkstra会超时,注意到其边权恒为1,所以可用一次bfs解决,同时记录路径即可)。代码总含有许多不成熟的地方,包括强行转换图的痕迹,请见谅,回头会修改的。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define MAXN 3004
#define MAXM 40010
#define HASHMOD 100003
#define INF 0x3f3f3f3f
typedef struct road {
	int fromCity;
	int toCity;
	int NO;
	struct road() {}
	struct road(int u, int v) { fromCity = u; toCity = v; }
	struct road(int u, int v, int No) { fromCity = u; toCity = v; NO = No; }
	bool operator == (struct road r) { 
		return (fromCity == r.fromCity&&toCity == r.toCity);
	}
}Road;
typedef struct cancellableVertex {
	int toNode;
	bool valid;
	struct cancellableVertex(int to) { toNode = to; valid = true; }
}CancellableVertex;
typedef struct Vertex {
	int weight;
	bool isValid;
	int pi;
}Vertex;
int allRoads[MAXN][MAXN];
Road roadIndex[MAXM];
vector originalGraph[MAXN];
vector roadGraph[MAXM];
Vertex roadVertices[MAXM];
int n, m, k, indexNumber;
int roadNumber(Road r)
{
	return allRoads[r.fromCity][r.toCity];
}
void input()
{
	memset(allRoads, 0xff, sizeof(allRoads));
	for (int i = 0; i < MAXN; i++)
		originalGraph[i].clear();
	memset(roadIndex, 0xff, sizeof(roadIndex));
	indexNumber = 0;
	for (int i = 0; i < m; i++) {
		int u, v, h;
		scanf("%d %d", &u, &v);
		if (roadNumber(Road(u, v)) < 0) {
			allRoads[u][v] = indexNumber;
			roadIndex[indexNumber] = Road(u, v,indexNumber);
			indexNumber++;
			originalGraph[u].push_back(v);
		}
		if (roadNumber(Road(v, u)) < 0) {
			allRoads[v][u] = indexNumber;
			roadIndex[indexNumber] = Road(v, u,indexNumber);
			indexNumber++;
			originalGraph[v].push_back(u);
		}
	}
	originalGraph[0].push_back(1);
	originalGraph[n].push_back(n+1);
	allRoads[0][1] = indexNumber;
	roadIndex[indexNumber] = Road(0, 1, indexNumber);
	indexNumber++;
	allRoads[n][n+1] = indexNumber;
	roadIndex[indexNumber] = Road(n, n+1, indexNumber);
	indexNumber++;
	//printf("Indexnumber:%d\n", indexNumber);
}
void banRoads()
{
	//time_t start, end;
	//start = time(NULL);
	for (int i = 0; i < k; i++) {
		int u, v, w, h1, h2;
		scanf("%d %d %d", &u, &v, &w);
		h1 = roadNumber(Road(u, v));
		h2 = roadNumber(Road(v, w));
		if (h1 < 0 || h2 < 0)
			continue;
		for(unsigned int j=0;j%d:", i,roadIndex[i].fromCity,roadIndex[i].toCity);
		for (unsigned int j = 0; j < roadGraph[i].size(); j++) {
			if (roadGraph[i][j].valid)
				printf("%d\t", roadGraph[i][j].toNode);
		}
		printf("\n");
	}
}
void buildRoadGraph()
{
	//time_t end, start;
	//start = time(NULL);
	for (int i = 0; i < MAXM; i++)
		roadGraph[i].clear();
	for (int i = 0; i <= n+1; i++) {
		for (unsigned int j = 0; j < originalGraph[i].size(); j++) {
			int tempRoadNumber = roadNumber(Road(i, originalGraph[i][j]));
			//printf("tempRoadNumber:%d\n", tempRoadNumber);
			int u = originalGraph[i][j];
			for (unsigned int v = 0; v < originalGraph[u].size(); v++) {
				int h = roadNumber(Road(u, originalGraph[u][v]));
				roadGraph[tempRoadNumber].push_back(CancellableVertex(h ));
			}
		}
	}
	//end = time(NULL);
	//printf("Index:%d\n", indexNumber);
	//printf("Build graph for %.2lf on %d %d %d\n", difftime(end, start), n, m, k);
}
int extractMin()
{
	int tempMin = INF;
	int tempMinIndex = -1;
	for (int i = 0; i < indexNumber; i++) {
		if (roadVertices[i].isValid&&roadVertices[i].weight<=tempMin) {
			tempMin = roadVertices[i].weight;
			tempMinIndex = i;
		}
	}
	if (tempMinIndex < 0)
		return tempMinIndex;
	roadVertices[tempMinIndex].isValid = false;
	return tempMinIndex;
}
int allMin;
vector minRoute;
void bfs(int s)
{
	for (int i = 0; i < indexNumber; i++) {
		roadVertices[i].isValid = false;
		roadVertices[i].weight = INF;
		roadVertices[i].pi = -1;
	}
	roadVertices[s].isValid = true;
	roadVertices[s].weight = 0;
	queue vertices;
	while (vertices.empty() == false)
		vertices.pop();
	vertices.push(s);
	while (vertices.empty() == false) {
		int u = vertices.front();
		vertices.pop();
		for (int i = 0; i < roadGraph[u].size(); i++) {
			if (roadGraph[u][i].valid) {
				int v = roadGraph[u][i].toNode;
				if (roadVertices[v].isValid == false) {
					roadVertices[v].isValid = true;
					roadVertices[v].weight = roadVertices[u].weight + 1;
					roadVertices[v].pi = u;
					vertices.push(v);
				}
			}
		}
	}
}
vector routeNumbers;
void getRoute(int s, int t)
{
	if (roadVertices[t].pi == s) {
		routeNumbers.push_back(s);
		routeNumbers.push_back(t);
	}
	else if (roadVertices[t].pi < 0)
		routeNumbers.push_back(s);
	else {
		getRoute(s, roadVertices[t].pi);
		routeNumbers.push_back(t);
	}
}
void getMinRoute(int s, int t)
{
	routeNumbers.clear();
	getRoute(s, t);
	minRoute.clear();
	for (unsigned int i = 0; i < routeNumbers.size(); i++)
		minRoute.push_back(routeNumbers[i]);
}
void prepareData()
{
	FILE *output = fopen("dataPrepare.txt", "w");
	if (output == NULL) {
		perror("Can't open preparedata!\n");
		return;
	}
	srand(time(NULL));
	for (int i = 0; i < 20; i++) {
		int n, m, k;
		n = rand() % 3000;
		if (n < 2)
			n += 2;
		m = rand() % 20000;
		if (m < 1)
			m += 2;
		k = rand() % 100000;
		fprintf(output,"%d %d %d\n", n, m, k);
		for (int i = 0; i < m; i++) {
			int u, v;
			u = rand() % n;
			v = rand() % n;
			if (u == 0)
				u = 1;
			if (v == 0)
				v = 1;
			fprintf(output,"%d %d\n", u, v);
		}
		for (int i = 0; i < k; i++) {
			int u, v, w;
			u = rand() % n;
			v = rand() % n;
			w = rand() % n;
			if (u == 0)
				u = 1;
			if (v == 0)
				v = 1;
			if (w == 0)
				w = 1;
			fprintf(output, "%d %d %d\n", u, v, w);
		}
		fprintf(output, "\n");
	}
	fclose(output);
}
void solveOne(int s)
{
	bfs(s);
	int tempMin = INF;
	int h = roadNumber(Road(n , n+1));
	tempMin = roadVertices[h].weight;
	if (tempMin < allMin) {
		getMinRoute(s, h);
		allMin = tempMin;
	}
	//printf("For solving %d costs %.2lf s\n", s, difftime(end, start));
}
void solve()
{
	allMin = INF;
	int h = roadNumber(Road(0, 1));
?	solveOne(h);
	if (allMin == INF)
		printf("-1\n");
	else {
		printf("%d\n", minRoute.size()-2);
		for (unsigned int i = 0; i < minRoute.size()-1; i++) {
			printf("%d%c", roadIndex[minRoute[i]].toCity,i==minRoute.size()-2?'\n':' ');
		}
	}
}
int main()
{
	while (scanf("%d %d %d", &n, &m, &k) != EOF) {
		input();
		buildRoadGraph();
		banRoads();
		solve();
	}
	return 0;
}

今天又重新整理了一下,得到一份稍微清洁点的代码贴上。498ms,还是有点慢啊。另外为什么vjudge和上官网提交有性能差异呢?

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define MAXN 3004
#define MAXM 40010
#define INF 0x3f3f3f3f
typedef struct road {
	int fromCity;
	int toCity;
	int NO;
	struct road() {}
	struct road(int u, int v) { fromCity = u; toCity = v; }
	struct road(int u, int v, int No) { fromCity = u; toCity = v; NO = No; }
	bool operator == (struct road r) { 
		return (fromCity == r.fromCity&&toCity == r.toCity);
	}
}Road;
typedef struct cancellableVertex {
	int toNode;
	bool valid;
	struct cancellableVertex(int to) { toNode = to; valid = true; }
}CancellableVertex;
typedef struct Vertex {
	int weight;
	bool isValid;
	int pi;
}Vertex;
int allRoads[MAXN][MAXN];
Road roadIndex[MAXM];
vector originalGraph[MAXN];
vector roadGraph[MAXM];
Vertex roadVertices[MAXM];
int n, m, k, indexNumber;
int roadNumber(Road r)
{
	return allRoads[r.fromCity][r.toCity];
}
void input()
{
	memset(allRoads, 0xff, sizeof(allRoads));
	for (int i = 0; i < MAXN; i++)
		originalGraph[i].clear();
	memset(roadIndex, 0xff, sizeof(roadIndex));
	indexNumber = 0;
	for (int i = 0; i < m; i++) {
		int u, v, h;
		scanf("%d %d", &u, &v);
		if (roadNumber(Road(u, v)) < 0) {
			allRoads[u][v] = indexNumber;
			roadIndex[indexNumber] = Road(u, v,indexNumber);
			indexNumber++;
			originalGraph[u].push_back(v);
		}
		if (roadNumber(Road(v, u)) < 0) {
			allRoads[v][u] = indexNumber;
			roadIndex[indexNumber] = Road(v, u,indexNumber);
			indexNumber++;
			originalGraph[v].push_back(u);
		}
	}
	originalGraph[0].push_back(1);
	originalGraph[n].push_back(n+1);
	allRoads[0][1] = indexNumber;
	roadIndex[indexNumber] = Road(0, 1, indexNumber);
	indexNumber++;
	allRoads[n][n+1] = indexNumber;
	roadIndex[indexNumber] = Road(n, n+1, indexNumber);
	indexNumber++;
}
void banRoads()
{
	for (int i = 0; i < k; i++) {
		int u, v, w, h1, h2;
		scanf("%d %d %d", &u, &v, &w);
		h1 = roadNumber(Road(u, v));
		h2 = roadNumber(Road(v, w));
		if (h1 < 0 || h2 < 0)
			continue;
		for(unsigned int j=0;j vertices;
	while (vertices.empty() == false)
		vertices.pop();
	vertices.push(s);
	while (vertices.empty() == false) {
		int u = vertices.front();
		vertices.pop();
		for (int i = 0; i < roadGraph[u].size(); i++) {
			if (roadGraph[u][i].valid) {
				int v = roadGraph[u][i].toNode;
				if (roadVertices[v].isValid == false) {
					roadVertices[v].isValid = true;
					roadVertices[v].weight = roadVertices[u].weight + 1;
					roadVertices[v].pi = u;
					vertices.push(v);
				}
			}
		}
	}
}
vector routeNumbers;
void getRoute(int s, int t)
{
	if (roadVertices[t].pi == s) {
		routeNumbers.push_back(s);
		routeNumbers.push_back(t);
	}
	else if (roadVertices[t].pi < 0)
		routeNumbers.push_back(s);
	else {
		getRoute(s, roadVertices[t].pi);
		routeNumbers.push_back(t);
	}
}
void solve()
{
	int h = roadNumber(Road(0, 1));
	bfs(h);
	if (roadVertices[indexNumber-1].weight == INF)
		printf("-1\n");
	else {
		routeNumbers.clear();
		getRoute(h, indexNumber - 1);
		printf("%d\n", routeNumbers.size()-2);
		for (unsigned int i = 0; i < routeNumbers.size()-1; i++) {
			printf("%d%c", roadIndex[routeNumbers[i]].toCity,i==routeNumbers.size()-2?'\n':' ');
		}
	}
}
int main()
{
	while (scanf("%d %d %d", &n, &m, &k) != EOF) {
		input();
		buildRoadGraph();
		banRoads();
		solve();
	}
	return 0;
}

你可能感兴趣的:(oj,odyssey)