码迷,mamicode.com
首页 > 移动开发 > 详细

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

时间:2015-08-20 14:59:14      阅读:240      评论:0      收藏:0      [点我收藏+]

标签:

题意很好理解,判断是否能从起点走到终点,每走到几个点就会获得这个点所代表的能量值,起点时自身带有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;
}

  

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

标签:

原文地址:http://www.cnblogs.com/modengdubai/p/4745066.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!