题意:给出n个点和m个边及起始点(相当于此问题中的出口点),求从起始点可到达的点的个数
思路:因为出口点为从其它点通过一些边后到达的终点,因此在添加边关系时,起点转为终点,终点转为起点。
代码如下:
#include<iostream>
#include <vector>
#include <queue>
#include <set>
#include <fstream>
#include <cstring>
using namespace std;
const int N = 110;
const int INF = 0x3fffffff;
class Solution
{
public:
void init(int n, int e, int t)
{
this->n = n;
this->e = e;
this->t = t;
for (int i = 0; i < n; i++) adjList[i].clear();
edges.clear();
}
void addEdge(int u, int v, int t)
{
Edge edge = {v, u, t};
edges.push_back(edge);
int size = edges.size();
adjList[v - 1].push_back(size - 1);
}
int dijkstra(int s)
{
for (int i = 0; i < n; i++)
{
d[i] = INF;
}
d[s - 1] = 0;
priority_queue<HeapNode> pq;
pq.push({0, s - 1});
set<int> done;
while (!pq.empty())
{
HeapNode curNode = pq.top(); pq.pop();
if (done.count(curNode.u)) continue;
done.insert(curNode.u);
int u = curNode.u;
for (size_t i = 0; i < adjList[u].size(); i++)
{
Edge& e = edges[adjList[u][i]];
if (d[e.from - 1] + e.cost < d[e.to - 1] && d[e.from - 1] + e.cost <= t)
{
d[e.to - 1] = d[e.from - 1] + e.cost;
pq.push({d[e.to - 1], e.to - 1});
}
}
}
int cnt = 0;
for (int i = 0; i < n; i++)
{
if (d[i] != INF) cnt++;
}
return cnt;
}
private:
class Edge
{
public:
int from, to, cost;
};
class HeapNode
{
public:
int d, u;
bool operator < (const HeapNode& other) const
{
return d > other.d;
}
};
private:
int n, e, t;
vector<Edge> edges;
vector<int> adjList[N];
int d[N];
};
int main()
{
Solution solver;
int cases;
#ifndef ONLINE_JUDGE
ifstream fin("f:\\OJ\\uva_in.txt");
streambuf* old = cin.rdbuf(fin.rdbuf());
#endif
cin >> cases;
while (cases--)
{
int n, e, t, m;
cin >> n >> e >> t;
solver.init(n, e, t);
cin >> m;
while (m--)
{
int u, v, t;
cin >> u >> v >> t;
solver.addEdge(u, v, t);
}
int cnt = solver.dijkstra(e);
cout << cnt << endl;
if (cases) cout << endl;
}
#ifndef ONLINE_JUDGE
cin.rdbuf(old);
#endif
return 0;
}
floyd_warshall算法实现如下:
#include <cstdio>
#include <fstream>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110;
const int INF = 0x3fffffff;
class Solution
{
public:
void init(int n, int e, int t)
{
this->n = n;
this->e = e;
this->t = t;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (i != j)
f[i][j] = INF;
else
f[i][j] = 0;
}
}
}
void addEdge(int u, int v, int t)
{
f[u - 1][v - 1] = t;
}
int floyd_warshall()
{
memcpy(dp, f, sizeof(f));
for (int k = 0; k < n; k++)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (dp[i][k] != INF && dp[k][j] != INF)
{
dp[i][j] = min(dp[i][k] + dp[k][j], dp[i][j]);
}
}
}
}
int ans = 0;
for (int i = 0; i < n; i++)
{
if (dp[i][e - 1] <= t)
{
ans++;
}
}
return ans;
}
private:
int n, e, t;
int f[N][N];
int dp[N][N];
};
int main()
{
#ifndef ONLINE_JUDGE
ifstream fin("D:\\program\\clion\\spoj.txt");
streambuf* old = cin.rdbuf(fin.rdbuf());
#endif
Solution solver;
int cases;
cin >> cases;
while (cases--)
{
int n, e, t, m;
cin >> n >> e >> t;
solver.init(n, e, t);
cin >> m;
while (m--)
{
int u, v, t;
cin >> u >> v >> t;
solver.addEdge(u, v, t);
}
int ans = solver.floyd_warshall();
cout << ans << endl;
if (cases) cout << endl;
}
#ifndef ONLINE_JUDGE
cin.rdbuf(old);
#endif
return 0;
}