题目链接
本题考查图的遍历,确实不容易啊!!难怪通过率那么低了
#include
using namespace std;
const int maxn = 10005;
const int inf = 0x3fffffff;
const int h = 10000;//hash散列运算
int N;
vector<int> G[maxn];
unordered_map<int, int> line;//标记站点所在线路,对每条线路上的每个站点做hash散列
bool vis[maxn];
vector<int> tempPath, optPath;
int optStep = inf, optTransCnt = inf;
void dfs(int now, int lastline, int E, int step)
{
if(now == E)
{
tempPath.push_back(now);
if(tempPath.size() < optStep)
{
optStep = tempPath.size();
optTransCnt = step;
optPath = tempPath;
}
else if(tempPath.size() == optStep && step < optTransCnt)
{
optTransCnt = step;
optPath = tempPath;
}
tempPath.pop_back();
return;
}
vis[now] = true;
tempPath.push_back(now);
for(int v = 0; v < G[now].size(); ++v)
{
int pos = G[now][v];
if(vis[pos] == false)
{
if(line[now * h + pos] != lastline)//与上一站不是同一条线路
dfs(pos, line[now * h + pos], E, step + 1);
else
dfs(pos, lastline, E, step);
}
}
vis[now] = false;
tempPath.pop_back();
}
int main(int argc, char *argv[]) {
scanf("%d", &N);
for(int i = 1; i <= N; ++i)
{
//线路上的前驱站点pre,线路起始first,终点last
int M, pre, first, last;
scanf("%d%d", &M, &pre);
for(int j = 0; j < M - 1; ++j)
{
int temp;//线路上的其余站
scanf("%d", &temp);
G[pre].push_back(temp);
G[temp].push_back(pre);
//散列保证中转站所在线路不同,hash值不同
line[pre * h + temp] = line[temp * h + pre] = i;
pre = temp;//更新前驱站点
}
}
int K;
scanf("%d", &K);
while(K--)
{
int start, end;
scanf("%d%d", &start, &end);
// memset(vis, false, sizeof(vis)); //每次dfs回溯都会初始化,不需要重复初始化
// tempPath.clear();
optStep = optTransCnt = inf;
dfs(start, 0, end, 0);
printf("%d\n", optPath.size() - 1);//起始站不算
int startLine = line[optPath[0] * h + optPath[1]];
int startPoint = optPath[0];
for(int i = 1; i < optPath.size() - 1; ++i)
{
if(line[optPath[i] * h + optPath[i + 1]] != startLine)
{
printf("Take Line#%d from %04d to %04d.\n", startLine, startPoint, optPath[i]);
startLine = line[optPath[i] * h + optPath[i + 1]];
startPoint = optPath[i];
}
}
printf("Take Line#%d from %04d to %04d.\n", startLine, startPoint, end);
}
return 0;
}
自增计算辨别transfer station
bfs由于会修改结构体中的step,不太适合多次查询,或者每次都初始化step(其实并没有影响step)
记录路径,使用1e4的二维结构体,每次查询清空,会影响效率 用链表存储,顺向还是逆向遍历,因为有两个方向(因为每次都是从一条线路的起始位置开始遍历)
一开始G的存储方式出现问题了(由于本题中,图的输入方式略有不同)
尝试写了bfs,dfs,最后发现自己存储图的方式有严重的问题,当时是用二维vector,每一行是一条线路。太想当然了,压根就不是图的存储方式!!根本算不上有向图无向图乱,存得乱七八糟的
#include
using namespace std;
const int maxn = 10005;
const int inf = 0x3fffffff;
struct Node{
int station;//站名
int line;//所属线路
int step;
Node(){}
Node(int s, int l)
{
station = s;
line = l;
}
}nodes[maxn];
int N, M, K;
vector<int> G[105];
map<int, int> isTransfer;//自增,访问过两次以上为transfer,loop的话自减
bool vis[maxn];
vector<int> pre[maxn];//路径前驱结点
vector<int> tempPath, optPath;
int tempStep, optStep = inf;
int bfs(int S, int E)
{
queue<Node> q;
nodes[S].step = 1;
Node start = nodes[S];
q.push(start);
vis[S] = true;
while(!q.empty())
{
Node now = q.front();
q.pop();
if(now.station == E)
{
return now.step;
}
int u = now.line;
for(int v = 0; v < G[u].size(); ++v)
{
int pos = G[u][v];
if(vis[pos] == true)
continue;
nodes[pos].step = now.step + 1;
Node temp = nodes[pos];
q.push(temp);
vis[pos] = true;
}
}
}
void dfs(int now, int E, int step)
{
if(now == E)
{
tempPath.push_back(now);
if(step < optStep)
{
optPath = tempPath;
}
tempPath.clear();
return;
}
vis[now] = true;
int u = nodes[now].line;
for(int v = 0; v < G[u].size(); ++v)
{
int pos = G[u][v];
if(vis[pos] == false)
{
dfs(pos, E, step + 1);
}
}
vis[now] = false;
}
int main(int argc, char *argv[]) {
scanf("%d", &N);
for(int i = 1; i <= N; ++i)
{
scanf("%d", &M);
for(int j = 0; j < M; ++j)
{
int station;
scanf("%d", &station);
nodes[station] = Node(station, i);
isTransfer[station]++;
G[i].push_back(station);
}
if(G[i][0] == G[i][G[i].size() - 1])//判断是否是loop
isTransfer[G[i][0]]--;
}
scanf("%d", &K);
while(K--)
{
int start, end;
scanf("%d%d", &start, &end);
memset(vis, false, sizeof(vis));
optPath.clear();
optStep = inf;
dfs(start, end, 0);
cout << optPath.size() <<endl;
}
/*for(map::iterator it = isTransfer.begin(); it != isTransfer.end(); ++it)
{
if(it->second >= 2)
{
cout << it->first << endl;
}
}*/
return 0;
}