您的位置:首页 > 其它

hdu1317(spfa判断正环+Floyd判断联通)

2015-08-20 14:23 369 查看
题意很好理解,判断是否能从起点走到终点,每走到几个点就会获得这个点所代表的能量值,起点时自身带有100能量值。

刚开始写了个裸地spfa,超时了,发现可能存在从起点走不到终点,而且还存在正环,这样程序永远也不会结束,改正后用Floyd判断起点和终点是否联通,然后用spfa求最长路,遇到环中的点时判断,环中的点是否能到达终点,能到达则输出“winnable”,因为可以在正环中获得无限能量值。 不能的话继续做spfa, 并且环中的点不再进入队列,这个换就被破坏了,这样就算图中有多个环也能处理。若没有环中的点可以到达终点,则判断dist数组中对应终点的值是否大于0。

#include <iostream>
#include <queue>
#include <memory.h>
#include <vector>
#include <stdio.h>
using namespace std;
vector<vector<int> > v;
vector<int> energy;
bool A[105][105];
int N;
void Floyd()
{
for(int k=0;k<N;k++)
{
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
if(A[i][k]&&A[k][j])//更新联通
A[i][j]=true;
}
}
}
}
bool spfa(int S,int E)
{
vector<int> dist;
vector<int> counter;
counter.resize(N);
dist.resize(N);
for(int i=0;i<N;i++)
{
dist[i]=0;
counter[i]=0;
}
dist[S]=100;
queue<int> Q;
Q.push(S);
counter[S]++;
while(!Q.empty())
{
int s=Q.front();
Q.pop();
for(int i=0;i<v[s].size();i++)
{
int e=v[s][i];
if(dist[s]+energy[e]>dist[e])
{
dist[e]=dist[s]+energy[e];
if(counter[e]<N)
{
Q.push(e);
counter[e]++;
}
else if(counter[e]>=N&&A[e][N-1])
{
return true;//此点不进入队列,从而破坏正环。并继续执行spfa,以防止出现第二个环能到达的情况。
}
}
}
}
return dist[N-1]>0;//判断是否不经过正环能走到(有可能图中无环或者通过环无法到达)。
}
int main()
{
while(scanf("%d",&N)&&N!=-1)
{
memset(A,false,sizeof(A));
v.clear();
v.resize(N);
energy.clear();
for(int i=0;i<N;i++)
{
int t,a;
scanf("%d",&t);
energy.push_back(t);
scanf("%d",&t);
for(int j=0;j<t;j++)
{
scanf("%d",&a);
v[i].push_back(a-1);
A[i][a-1]=true;
}
}
Floyd();
if(!A[0][N-1])
cout<<"hopeless"<<endl;
else if(spfa(0,N-1))
cout<<"winnable"<<endl;
else
cout<<"hopeless"<<endl;
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: