今天做了一道hdu的单源最短路径问题,其问一个图中所有节点最短路径和以及删去某条边后相应的最短路径和。直接计算会超时,所以要适当记录路径,当删去的边不在某个顶点的最短路中的时候才再跑一遍bfs。相应的注意记录和计算即可。之前是将所有边的最短路径记录到了一起,导致不能很好的复用,将其分开记录才能很好的发挥预处理的作用,算是学习到一点数据结构处理的思路(不过说真的,有时候感觉我数据结构那里才是学的最差的一部分)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <assert.h>
using namespace std;
#define MAXN 101
#define INF 0x3f3f3f3f
typedef struct edge {
int fromCity;
int toCity;
int weight;
bool isValid;
struct edge(int v, int w) { toCity = v; weight = w; isValid = true; }
struct edge(int u, int v, int w) { fromCity = u; toCity = v; weight = w; isValid = true; }
bool operator != (const struct edge & v) {
if (fromCity == v.fromCity&&toCity == v.toCity&&isValid==v.isValid)
return false;
else if (fromCity == v.toCity&&toCity == v.fromCity&&isValid==v.isValid)
return false;
return true;
}
}Edge;
typedef int Vertex;//restore their ancestors
bool operator < (const Edge &a, const Edge &b)
{
return a.fromCity<b.fromCity||(a.fromCity==b.fromCity&&a.toCity < b.toCity);
}
vector<Vertex > vertices;
vector<Vertex > verticesPi;
bool verticesInArray[MAXN];
vector<Edge > solvingEdges[MAXN];
vector<Edge > edgeList;
set<Edge> shortestPathEdges[MAXN];
int dijkstraWeight[MAXN];
int dijkstraWeightCopy[MAXN];
int sum;
int N, M;
void init()
{
edgeList.clear();
for (int i = 0; i < N; i++)
solvingEdges[i].clear();
for(int i=0;i<N;i++)
shortestPathEdges[i].clear();
}
void input()
{
int city1, city2;
for (int i = 0; i < M; i++) {
scanf("%d %d", &city1, &city2);
solvingEdges[city1 - 1].push_back(Edge(city1 - 1, city2 - 1, 1));
solvingEdges[city2 - 1].push_back(Edge(city2 - 1, city1 - 1, 1));
edgeList.push_back(Edge(city1 - 1, city2 - 1, 1));
}
}
void bfs(int s)
{
for (int i = 0; i < N; i++) {
vertices[i] = INF;
verticesPi[i] = -1;
verticesInArray[i] = false;
}
vertices[s] = 0;
verticesPi[s] = -1;
queue<int > bfsQueue;
bfsQueue.push(s);
while (bfsQueue.empty() == false) {
int u = bfsQueue.front();
bfsQueue.pop();
for (int i = 0; i < solvingEdges[u].size(); i++) {
if (solvingEdges[u][i].isValid) {
int v = solvingEdges[u][i].toCity;
if (verticesInArray[v] == false) {
verticesInArray[v] = true;
vertices[v] = vertices[u] + 1;
verticesPi[v] = u;
bfsQueue.push(v);
}
}
}
verticesInArray[u] = true;
}
}
void dijkstraForOneVertex(int s, Edge disappearEdge)
{
vertices.clear();
for (int i = 0; i < N; i++)
vertices.push_back(INF);
vertices[s] = 0;
dijkstraWeight[s] = 0;
verticesPi.clear();
for (int i = 0; i < N; i++)
verticesPi.push_back(-1);
int u = disappearEdge.fromCity;
int v = disappearEdge.toCity;
int k, l;
bool set = false;
for (k = 0; k < solvingEdges[u].size(); k++) {
if (solvingEdges[u][k].toCity == v) {
solvingEdges[u][k].isValid = false;
set = true;
break;
}
}
for (l = 0; l < solvingEdges[v].size(); l++) {
if (solvingEdges[v][l].toCity == u) {
solvingEdges[v][l].isValid = false;
break;
}
}
bfs(s);
if (set) {
solvingEdges[v][l].isValid = true;
solvingEdges[u][k].isValid = true;
}
sum = 0;
for (int i = 0; i < N; i++) {
if (vertices[i] >= INF) {
sum = INF;
break;
}
sum += vertices[i];
}
dijkstraWeight[s] = sum;
}
vector<int > tempo;
void getShortestEdges(int i, int j)
{
if (i == j)
tempo.push_back(i);
else if (verticesPi[j] == i) {
tempo.push_back(i);
tempo.push_back(j);
}
else if (verticesPi[j] < 0)
return;
else {
getShortestEdges(i, verticesPi[j]);
tempo.push_back(j);
}
}
void addShortestEdges(int s)
{
for (int i = 0; i < N; i++) {
if (i != s) {
tempo.clear();
getShortestEdges(s, i);
for (int j = 0; j < tempo.size() - 1; j++) {
shortestPathEdges[s].insert(Edge(tempo[j], tempo[j + 1], 1));
shortestPathEdges[s].insert(Edge(tempo[j + 1], tempo[j], 1));
}
}
}
}
int getSum()
{
int ret = 0;
for (int i = 0; i < N; i++)
ret += dijkstraWeight[i];
return ret;
}
void solve()
{
memset(dijkstraWeight, 0, sizeof(dijkstraWeight));
sum = 0;
dijkstraForOneVertex(0, Edge(0,-1, -1));
for(int i=0;i<N;i++)
if (dijkstraWeight[i] >= INF) {
for(int j=0;j<M;j++)
printf("INF\n");//unconnected
return;
}
addShortestEdges(0);
for (int i = 1; i < N; i++) {
dijkstraForOneVertex(i, Edge(0, -1,-1));
addShortestEdges(i);
}
for (int i = 0; i < N; i++)
dijkstraWeightCopy[i] = dijkstraWeight[i];
set<Edge >::iterator it;
int presentSum = getSum();
for (int i = 0; i < edgeList.size(); i++) {
for (int j = 0; j < N; j++)
dijkstraWeight[j] = dijkstraWeightCopy[j];
bool appeared = false;
for (int j = 0; j < N; j++) {
it = shortestPathEdges[j].find(edgeList[i]);
if (it != shortestPathEdges[j].end()) {
appeared = true;
break;
}
}
if (!appeared) {
printf("%d\n", presentSum);
continue;
}
else {
bool isInf = false;
for (int j = 0; j < N; j++) {
it = shortestPathEdges[j].find(edgeList[i]);
if (it == shortestPathEdges[j].end())
continue;
dijkstraForOneVertex(j, Edge(it->fromCity,it->toCity,it->weight));
for (int k = 0; k < N; k++) {
if (dijkstraWeight[k] >= INF) {
isInf = true;
break;
}
}
if (isInf) {
printf("INF\n");
break;
}
}
if (!isInf)
printf("%d\n", getSum());
}
}
}
int main()
{
while (scanf("%d %d", &N, &M) != EOF) {
init();
input();
solve();
}
return 0;
}