hdu1217

Hdu1217 这题很棒突破了传统的最短路的,但思想都是一样的,一道挺新颖的题目。

用了两种方法解 一是 Spfa 二是Floyd(-_-终于能用Floyd了,一直没机会)

Spfa                        Floyd                

                   

不过在用Spfa算法时,在处理环的问题网上的题解是在队列循环中加上if(dis[开始]>1.0) return ture 而我是在处理完队列循环后再加这个判断的,发现时间竟然查了10几倍,感觉好神奇。(PS:前者还有个好处,不用处理环的问题)


Spfa

#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<list>
using namespace std;
typedef long long lld;
typedef unsigned int ud;
#define Inf INT_MAX/2//int最大
#define Min(x,y) (x)<(y)?(x):(y)
#define Max(x,y) (x)>(y)?(x):(y)
#define PQ priority_queue
#define Q queue
#define N 33
int n,m;
struct Node
{
    int v,next;
    double w;
}edge[N*N];
double dis[N];
int mark[N],head[N],cnt[N];
char str[N*N][N];
char buff[N];

int GetCur(char *s)
{
    for(int i=1;i<=n;i++)
        if(strcmp(s,str[i])==0)
            return i;
    return -1;
}

bool Spfa(int s)
{
    memset(dis,0,sizeof dis);
    memset(mark,0,sizeof mark);
    memset(cnt,0,sizeof cnt);

    dis[s]=1.0; mark[s]=1;
    Q<int> q;
    q.push(s);
    while(!q.empty())
    {
        int e=q.front(); q.pop();
        mark[e]=0;
        for(int i=head[e];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            if(dis[e]*edge[i].w>dis[v])
            {
                dis[v]=dis[e]*edge[i].w;

    

                if(!mark[v])
                {
                    q.push(v);
                    mark[v]=1;

                    if(++cnt[v]>n)
                        break;
                }
            }
        }
    }
    if(dis[s]>1.0)
        return true;
    return false;
}

int main()
{
    int cas=1;
    while(scanf("%d",&n)&&n)
    {
        memset(head,-1,sizeof head);
        for(int i=1;i<=n;i++)
            scanf("%s",str[i]);
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            int u,v;
            double w;
            scanf("%s",buff);
            u=GetCur(buff);
            scanf("%lf%s",&w,buff);
            v=GetCur(buff);
            
            edge[i].v=v;
            edge[i].w=w;
            edge[i].next=head[u];
            head[u]=i;
        }
        int find=false;
        for(int i=1;i<=n;i++)
        {
            if(Spfa(i))
            {
                find=true;
                break;
            }
        }
        printf("Case %d: ",cas++);
        if(find)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}
Floyd

#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<list>
using namespace std;
typedef long long lld;
typedef unsigned int ud;
#define Inf INT_MAX/2//int最大
#define Min(x,y) (x)<(y)?(x):(y)
#define Max(x,y) (x)>(y)?(x):(y)
#define PQ priority_queue
#define Q queue
#define N 33
double map[N][N];
char str[N*N][N];
char a[N],b[N];
int n,m;
int u,v;
double w;

int GetCur(char *s)
{
    for(int i=1;i<=n;i++)
        if(strcmp(s,str[i])==0)
            return i;
    return -1;
}

void Floyd()
{
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(map[i][k]*map[k][j]>map[i][j])
                    map[i][j]=map[i][k]*map[k][j];
}

int main()
{
    int cas=1;
    while(scanf("%d",&n)&&n)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                if(i==j)
                    map[i][j]=1.0;
                else
                    map[i][j]=0.0;
            }

        for(int i=1;i<=n;i++)
            scanf("%s",str[i]);
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%s%lf%s",a,&w,b);
            u=GetCur(a);
            v=GetCur(b);
            map[u][v]=w;
        }
        Floyd();
        int find=false;
        for(int i=1;i<=n;i++)
            if(map[i][i]>1.0)
                find=true;
        printf("Case %d: ",cas++);
        if(find)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}
/*
3
USDollar
BritishPound
FrenchFranc
3
USDollar 0.5 BritishPound
BritishPound 10.0 FrenchFranc
FrenchFranc 0.21 USDollar

3
USDollar
BritishPound
FrenchFranc
6
USDollar 0.5 BritishPound
USDollar 4.9 FrenchFranc
BritishPound 10.0 FrenchFranc
BritishPound 1.99 USDollar
FrenchFranc 0.09 BritishPound
FrenchFranc 0.19 USDollar

0

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值