这题关键在于这个used[]数组的使用,非常的巧妙
used[]我是借鉴别人的!
先将某个房间的id在used数组中标号,使得used[id]=1,然后从0开始深度优先遍历,只要这次遍历无法达到et房间,则说明这个id是必经之路。对id的遍历,我用了贪心算法的思维,将et的入度bfs了,然后用队列遍历id
#include<iostream>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<vector>
#include<set>
#include<queue>
using namespace std;
struct node {
int index;
vector<int> in;
vector<int> out;
};
vector<node> map;
int n, et;
int used[110];
int vis[110];
int dfs(int id) {
if (id == et) {
return 1;
}
vector<int> ne = map[id].out;
for (int i = 0; i < ne.size(); i++) {
if (!used[ne[i]]) {
used[ne[i]] = 1;
if (dfs(ne[i])) return 1;
used[ne[i]] = 0;
}
}
return 0;
}
int main() {
int t;
cin >> t;
while (t--) {
map.clear();
memset(vis, 0, sizeof(vis));
cin >> n >> et;
string inf;
cin.ignore();
while (getline(cin, inf)) {
if (inf.length() == 0) {
break;
}
int ind = inf.find_first_of(' ');
int o = stoi(inf.substr(0, ind));
int d = stoi(inf.substr(ind + 1, inf.length() - ind));
int mx = max(o + 1, d + 1);
if (map.size() < mx) {
map.resize(mx);
}
map[o].out.push_back(d);
map[d].in.push_back(o);
}
if (find(map[0].out.begin(), map[0].out.end(), et) != map[0].out.end()) {
cout << "Put guards in room 0.\n";
if (t) cout << endl;
continue;
}
queue<int> q;
for (int i = 0; i < map[et].in.size(); i++) {
q.push(map[et].in[i]);
vis[map[et].in[i]] = 1;
}
int ans = 0;
while (!q.empty()) {
int room = q.front();
q.pop();
if (room == et)continue;
memset(used, 0, sizeof(used));
used[0] = 1;
used[room] = 1;
if (!dfs(0)) {
ans = room;
break;
} else {
vector<int> pre = map[room].in;
for (int i = 0; i < pre.size(); i++) {
if (!vis[pre[i]]) {
q.push(pre[i]);
vis[pre[i]] = 1;
}
}
}
}
printf("Put guards in room %d.\n", ans);
if (t) cout << endl;
}
}