这题应该要先用dfs来找是不是有能把能量变成无限大的循环,有的话,找一下这个们能不能到最后。。没有就dfs到结束就行。
刚开始我的做法是用了两个bfs,先用其中一个,判断是不是能够出去,能的话,就用另个dfs强行搜索,但是超时了。
AC代码:
#include<stdio.h>
#include<iostream>
#include<queue>
using namespace std;
const int N = 105;
struct room {
int engry;
int fengry;
int roomn;
int waynum;
int wayto[N];
};
bool vis[N],visx[N];
room r[N];
room r1,r2;
bool ok,canbe;
int roomnum;
int d;
queue<room> q,q2;
void initx () {
for (int i = 0; i < N ; i++)
visx[i] = false;
}
void init() {
for (int i = 0 ; i < N ; i++) {
r[i].engry = 0;
r[i].waynum = 0;
r[i].fengry = 0;
vis[i] = false;
}
while (!q.empty())
q.pop();
while (!q2.empty())
q2.pop();
ok = false;
canbe = false;
d = 0;
}
void reach(int x) {
initx();
r1 = r[x];
q2.push(r1);
while (!q2.empty()) {
r1 = q2.front();
q2.pop();
visx[r1.roomn] = true;
for (int i = 0; i < r1.waynum ;i++) {
if (visx[r1.wayto[i] - 1] == false) {
if (r1.wayto[i] == roomnum) {
ok = true;
return;
}
q2.push(r[r1.wayto[i] - 1]);
}
}
}
return ;
}
void dfs(int x,int eng) {
if(ok == true)
return ;
if (eng + r[x].engry > 0 ) {
if (vis[x] == true && eng + r[x].engry > r[x].fengry) {
reach(r[x].roomn);
}
if(vis[x] == true)
return ;
if (r[x].roomn == roomnum - 1) {
ok = true;
return;
}
vis[x] = true;
r[x].fengry = eng + r[x].engry;
for (int i = 0 ;i < r[x].waynum ;i++) {
dfs( r[x].wayto[i] - 1,r[x].fengry);
}
}
}
int main () {
while(cin >> roomnum){
init();
if (roomnum == -1)
break;
for (int i = 0 ; i < roomnum ; i++ ){
r[i].roomn = i;
cin >> r[i].engry;
cin >> r[i].waynum;
for (int j = 0; j < r[i].waynum ; j++) {
cin >> r[i].wayto[j];
}
}
dfs(0 ,100);
if (ok == true)
printf ("winnable\n");
else
printf("hopeless\n");
}
return 0;
}
之前超时的代码:
#include<stdio.h>
#include<iostream>
#include<queue>
using namespace std;
const int N = 105;
struct room {
int engry;
int fengry;
int roomn;
int waynum;
int wayto[N];
};
bool vis[N];
room r[N];
room r1,r2;
bool ok,canbe;
int roomnum;
int d;
queue<room> q,q2;
void init() {
for (int i = 0 ; i < N ; i++) {
r[i].engry = 0;
r[i].waynum = 0;
vis[i] = false;
}
while (!q.empty())
q.pop();
while (!q2.empty())
q2.pop();
ok = false;
canbe = false;
d = 0;
}
void bfs(){
r1.fengry = 100;
r1.engry = 0;
r1.roomn = 0;
r1.waynum = r[0].waynum;
for (int i = 0; i < r[0].waynum ; i++)
r1.wayto[i] = r[0].wayto[i];
q.push(r1);
while (!q.empty()) {
r1 = q.front();
q.pop();
for (int i = 0; i < r1.waynum; i++) {
if (r1.fengry + r[r1.wayto[i] - 1].engry > 0 ) {
if (r[r1.wayto[i] - 1].roomn == roomnum - 1 ) {
ok = true;
break;
}
r[r1.wayto[i] - 1].fengry = r1.fengry + r[r1.wayto[i] - 1].engry;
q.push(r[r1.wayto[i] - 1]);
}
}
if (ok == true)
break;
}
}
bool reach() {
r1 = r[0];
q2.push(r1);
while (!q2.empty()) {
r1 = q2.front();
q2.pop();
vis[r1.roomn] = true;
for (int i = 0; i < r1.waynum ;i++) {
if (vis[r1.wayto[i] - 1] == false) {
if (r1.wayto[i] == roomnum) {
return true;
}
q2.push(r[r1.wayto[i] - 1]);
}
}
}
return false;
}
int main () {
while(cin >> roomnum){
init();
if (roomnum == -1)
break;
for (int i = 0 ; i < roomnum ; i++ ){
r[i].roomn = i;
cin >> r[i].engry;
cin >> r[i].waynum;
for (int j = 0; j < r[i].waynum ; j++) {
cin >> r[i].wayto[j];
}
}
canbe = reach();
if (canbe == true)
bfs();
if (ok == true)
printf ("winnable\n");
else
printf("hopeless\n");
}
return 0;
}