hdu 1317 XYZZY bellman_ford判环+floyd

来源:互联网 发布:淘宝上的苹果官网 编辑:程序博客网 时间:2024/05/29 15:42

题意:玩家能量初始值有100,有100个房间,每个房间有一个大于-100小于100的能量值,每个房间与其他一些房间单向联通,玩家走到一个房间后能量加上房间的能量值,房间可以重复进入。若玩家的能量小于等于0,玩家输,若玩家到达终点,玩家赢。

以房间为点,从房间到房间建有向边,边的权值为进入的房间的能量值。求初始点到各点的剩余最大能量,注意如果出现环,要判断这个环是否与终点联通。判断连通性需要用floyd进行预处理。

判环应该用bellman,此题的数据比较弱,用spfa的代码也能AC,但应该是错的。

举个例子:同时出现两个环,一个与终点联通,一个不连通。若spfa先判断不连通的环时,会直接返回玩家输,而正确结果应该是赢。

先给出bellman_ford代码:

#include<cstdio>#include<cmath>#include<cstring>#include<iostream>#define N 110#define M 11000#define INF 0x7ffffffusing namespace std;int r[N][N],n,val[N],d[N],cnt;struct node{    int u,v;}e[M];void floyd(){    for(int k=1;k<=n;k++)        for(int i=1;i<=n;i++)            for(int j=1;j<=n;j++)                r[i][j]=max(r[i][j],r[i][k]&r[k][j]);}int bellman_ford(int s,int t){    for(int i=1;i<=n;i++)   d[i]=-INF;    d[s]=100;    for(int i=0;i<n;i++)    {        for(int j=0;j<cnt;j++)        {            int u=e[j].u,v=e[j].v;            if(d[u]+val[v]>0)   d[v]=max(d[v],d[u]+val[v]);        }    }    for(int i=0;i<cnt;i++)    {        int u=e[i].u,v=e[i].v;        if(d[u]+val[v]>0&&d[v]<d[u]+val[v]&&r[v][t])    return 1;    }    return d[t]>0;}int main(){    while(~scanf("%d",&n)&&n!=-1)    {        cnt=0;        memset(r,0,sizeof(r));        for(int i=1;i<=n;i++)        {            int nn;            scanf("%d%d",&val[i],&nn);            for(int j=0;j<nn;j++)            {                int c;                scanf("%d",&c);                e[cnt].u=i;                e[cnt++].v=c;                r[i][c]=1;            }        }        floyd();        if(bellman_ford(1,n))   cout<<"winnable"<<endl;        else    cout<<"hopeless"<<endl;    }}

AC的spfa代码:

#include <iostream>#include<cstdio>#include<cstring>#include<cmath>#include<queue>#define N 110#define INF 0x7ffffffusing namespace std;int n,val[N],mp[N][N],d[N],v[N],num[N],r[N][N];void floyd(){    for(int k=1;k<=n;k++)        for(int i=1;i<=n;i++)            for(int j=1;j<=n;j++)                r[i][j]=max(r[i][j],r[i][k]&r[k][j]);}int spfa(int s,int t){    for(int i=1;i<=n;i++)    {        num[i]=0;        d[i]=-INF;        v[i]=0;    }    queue<int> q;    q.push(s);    v[s]=1;    d[s]=100;    num[s]++;    while(!q.empty())    {        int c=q.front();        q.pop();        v[c]=0;        for(int i=1;i<=n;i++)        {            if(d[c]+mp[c][i]>0&&d[i]<d[c]+mp[c][i])            {                d[i]=d[c]+mp[c][i];                if(!v[i])                {                    if(++num[i]>=n)  return r[i][t];                    v[i]=1,q.push(i);                }            }        }    }    if(d[t]>0) return 1;    return 0;}int main(){    while(~scanf("%d",&n)&&n!=-1)    {        memset(mp,0,sizeof(mp));        memset(r,0,sizeof(r));        for(int i=1;i<=n;i++)        {            int nn;            scanf("%d%d",&val[i],&nn);            for(int j=0;j<nn;j++)            {                int c;                scanf("%d",&c);                mp[i][c]=1;                r[i][c]=1;            }        }        for(int i=1;i<=n;i++)            for(int j=1;j<=n;j++)            {                if(mp[i][j]==0) mp[i][j]=-INF;                else    mp[i][j]*=val[j];            }        floyd();        if(spfa(1,n))   cout<<"winnable"<<endl;        else cout<<"hopeless"<<endl;    }}



0 0
原创粉丝点击