(spfa) XYZZY (P1932)

来源:互联网 发布:python 字典 输入 编辑:程序博客网 时间:2024/04/28 18:50

题 意:一个单向图,第一个结点有权值。每到一个结点加上该点的值。

            当在该点加上的权值为正数是才可以向下一个点移动。

            求从结点1是否能到达结点N


解法:先用floyd计算出每点是否可到N点。再spfa


特别注意:对于每一个结点的总权值更新时要检查是否该点可达N点。

                       如果不可达N点,但该点又在负圈中,就可能会出现错误答案。因为有这样的情况时

                     就可以达N,但实际情况可能达不到。


网址:http://poj.org/problem?id=1932


#include<iostream>#include<queue>#include<vector>using namespace std;int n;vector<int> v[111]; int go[111];int canget[111][111];bool bfs(){int i,j,k;queue<int> q;bool vis[111];memset(vis,false,sizeof(vis));vis[1]=true;q.push(1);while (!q.empty()){int d=q.front();q.pop();if (d==n)return true;for (i=0;i<v[d].size();i++) if (!vis[v[d][i]]){vis[v[d][i]]=true;q.push(v[d][i]);}}return false;}bool spfa(){int i,j,k;int dis[111];bool vis[111];int intimes[111];memset(intimes,0,sizeof(intimes));memset(dis,0,sizeof(dis));memset(vis,false,sizeof(vis));dis[1]=100;deque<int> q;q.push_back(1);vis[1]=true;intimes[1]=1;while (!q.empty()){int d=q.front();q.pop_front();vis[d]=false;if (intimes[d]>=n)return true;if (d==n)return true;if (dis[d]<=0)continue;for (i=0;i<v[d].size();i++) if (dis[v[d][i]]<dis[d]+go[v[d][i]] && canget[v[d][i]][n])//canget必加,不然会有不达n的点i有intimes[i]>=n {dis[v[d][i]]=dis[d]+go[v[d][i]];if (!vis[v[d][i]]){vis[v[d][i]]=true;q.push_front(v[d][i]);intimes[v[d][i]]++;}}}if (dis[n]>0)return true;return false;}int main(){freopen("in","r",stdin);int i,j,k;while (cin>>n,n!=-1){memset(canget,0,sizeof(canget));for (i=1;i<=n;i++){cin>>go[i]>>k;v[i].clear();while (k--)cin>>j,v[i].push_back(j),canget[i][j]=1;canget[i][i]=1;  //自身可到 }for (k=1;k<=n;k++)for (i=1;i<=n;i++)for (j=1;j<=n;j++) if (canget[i][k] && canget[k][j])  canget[i][j]=1;  //记录从1是否可到n if (!canget[1][n]/*!bfs()*/){cout<<"hopeless"<<endl;continue;}if (spfa())cout<<"winnable"<<endl;elsecout<<"hopeless"<<endl;}}


0 0
原创粉丝点击