今天终于做出了一道困扰我一学期的题,就是这道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;
}