题意: 多组数据,首行数字表示有n
个房间,接下来n行第一个数表示第i
个房间的能量值,然后数值k
表示这个房间能通往k个房间。每个房间从1到n编号。要求从房间1走到房间n,途中必须保证能力值大于0。可以多次到达同一个房间多次吸收能量,但是房间间的路是单向边。
题解: 两个关键,1
途中的能力值必须大于0,2
可以反复到达一个有收益的房间。第一点还是容易保证的;关键在于2,既要能构成一个环、其能力值的收益还必须为正、并且这个环能通向终点。
结构体存边
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
int n, d[105];
struct node{
int v, w;
node(int b, int c) { v = b; w = c;}
};
vector<node> e[105];
void init(){
for (int i = 0; i <= n; i++){
d[i] = 0;
e[i].clear();
}
}
int spfa(){
if(n == 1) return 1;
queue<int> q;
int inq[105] = {0}, vis[105] = {0};
d[1] = 100, inq[1] = 1;
q.push(1);
while(!q.empty()){
int s = q.front();
q.pop();
vis[s]++, inq[s] = 0;
if(vis[s] == n+1) continue;
if(vis[s] == n) d[s] = 100000;//一共n个房间,就算剩下n-1个房间全能通向s房间,
//访问次数到达n次就表明能构成环。此时只要把能量值调到足够大就可以了。
for (int i = 0; i < e[s].size(); i++){
int v = e[s][i].v, w = e[s][i].w;
if (d[v] < d[s] + w){
d[v] = d[s] + w;
if(d[n] > 0) return 1;
if(!inq[v])
inq[v] = 1, q.push(v);
}
}
}
return 0;
}
int main(){
while(cin >> n){
if(n == -1) break;
init();
for (int i = 1; i <= n; i++){
int w, k, v;
cin >> w >> k;
while(k--){
cin >> v;
e[i].push_back(node(v, w));
}
}
if(spfa())
cout << "winnable" << endl;
else
cout << "hopeless" << endl;
}
return 0;
}
二维数组存边
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int inf = 0x3f3f3f3f;
int n, d[105];
int map[105][105];
void init(){
for (int i = 1; i <= n; i++){
d[i] = 0;
for (int j = 1; j <= n; j++)
map[i][j] = -inf;
}
}
int spfa(int s){
if(n==1) return 1;
queue<int>q;
int inq[105] = {0}, vis[105] = {0};
d[s] = 100, inq[s] = 1;
q.push(s);
while(!q.empty()){
s = q.front(), q.pop();
vis[s]++, inq[s] = 0;
if(vis[s] == n+1) continue;
if(vis[s] == n) d[s] = 100000;
for (int i = 1; i <= n; i++)
if (map[s][i] != -inf)
if (d[i] < d[s] + map[s][i]){
d[i] = d[s] + map[s][i];
if (d[n] > 0)
return 1; //走到第n点
if (!inq[i])
inq[i] = 1, q.push(i);
}
}
return 0;
}
int main(){
while(cin >> n){
if(n == -1) break;
init();
for (int i = 1; i <= n; i++){
int p, k, a;
cin >> p >> k;
while(k--){
cin >> a;
map[i][a] = p;
}
}
if(spfa(1))
cout << "winnable" << endl;
else
cout << "hopeless" << endl;
}
return 0;
}