POJ3259-Wormholes-( spfa || Bellman_Ford )

题意:有n块田,之间有m条无向边表示路径,权值表示走过需要花费的时间。有w对虫洞,虫洞是单向的,表示穿越一定时间到过去,并且回到虫洞指向的点,问一个人有没有可能通过虫洞回到某个起点,并且在从这个起点出发之前的时间,因为这样可以看到过去的自己。

解题:判断负圈,模板题。

//记录一下模板

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<math.h>
#include<string>
#include<map>
#include<queue>
#include<stack>
#include<set>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;


int n,m,w;
struct node
{
    int to;
    int val;
};
vector<node>e[505];
int num[505];
int d[505];
bool vis[505];

bool spfa()
{
    queue<int>que;
    que.push(1);
    d[1]=0;
    vis[1]=true;
    num[1]=1;
    while( que.size() )
    {
        int q=que.front();///q是当前结点
        que.pop();
        vis[q]=false;
        int len=e[q].size();
        for(int i=0;i<len;i++)
        {
            int next=e[q][i].to;
            int cost=e[q][i].val;
            if( d[next] > d[q]+cost )
            {
                d[next]=d[q]+cost;
                if( !vis[next] )///没有入队
                {
                    num[next]++;
                    if( num[next]>=n )
                        return false;///入了这么多次,存在负圈
                    vis[next]=true;///入队标记
                    que.push(next);
                }

            }
        }
    }
    return true;
}




int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {

        scanf("%d%d%d",&n,&m,&w);///点、边、负边
        memset(d,inf,sizeof(d));
        memset(num,0,sizeof(num));
        memset(vis,false,sizeof(vis));
        for(int i=1;i<=n;i++)
            e[i].clear();

        ///正边+负边总数
        int a,b,c;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);///起点,终点,权值
            e[a].push_back({b,c});
            e[b].push_back({a,c});
        }
        for(int i=0;i<w;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            e[a].push_back({b,-c});

        }
        if( spfa() )
            printf("NO\n");
        else
            printf("YES\n");

    }
    return 0;
}
spfa模板
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<math.h>
#include<string>
#include<map>
#include<queue>
#include<stack>
#include<set>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

struct edge
{
    int from;
    int to;
    int val;
};
edge e[5555];///无向边*2+有向边
int d[505];///各个点到起点的距离
int n,m,w,cnt;
int a,b,c;

void add(int x,int y,int z)
{
    e[cnt].from=x;
    e[cnt].to=y;
    e[cnt].val=z;
    cnt++;
}

bool Bellman_Ford()//贝尔曼福特
{
    d[1]=0;///把1作为起点
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<cnt;j++)
        {
            if( d[ e[j].from ] > d[ e[j].to ] + e[j].val  )
                d[ e[j].from ] = d[ e[j].to ] + e[j].val;
        }
    }
    for(int j=0;j<cnt;j++)///第n+1次,还能对边松弛则说明存在负环
    {
        if( d[ e[j].from ] > d[ e[j].to ] + e[j].val  )
            return false;
    }
    return true;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(d,inf,sizeof(d));
        scanf("%d%d%d",&n,&m,&w);///点、边、负边
        cnt=0;///正边+负边的总边数
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);///无向边
        }
        for(int i=0;i<w;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,-c);
        }
        if( Bellman_Ford() )
            printf("NO\n");
        else
            printf("YES\n");

    }
    return 0;
}
Bellman_Ford模板

 

posted @ 2019-07-20 23:29  守林鸟  阅读(132)  评论(0编辑  收藏  举报