POJ3259Wormholes

一.原题链接:http://poj.org/problem?id=3259

二.题目大意:从一个田地开始可以花Ts到另一田地,并且回来是同一时间。(双向边)田地之间有虫洞,单向边,走过虫洞可以使时间倒流。问能不能从某一个田地出发,回到改田地使得时光倒流。

三.思路:就是判断有没有负环,有的话就YES,否则NO。

四.AC代码:

spfa:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;

const int MAX_SIZE = 520,
          INF = 1<<29,
          MOD = 1000000007;


int graph[MAX_SIZE][MAX_SIZE];
//PedgeNum 表示正边数,NedgeNum表示负边数
int nodeNum, PedgeNum, NedgeNum;


void initGraph()
{
    int i, j;
    for(i = 0; i < MAX_SIZE; i++)
        for(j = 0; j < MAX_SIZE; j++)
            graph[i][j] = INF;
}

//有负环返回 false, 否则返回 true
bool spfa()
{
    int dist[MAX_SIZE], cnt[MAX_SIZE] = {0}, i, j, cur;
    bool inQue[MAX_SIZE] = {0};
    queue <int> que;
//设0为起点
    for(i = 1; i <= nodeNum; i++)
        dist[i] = (1 == i? 0:INF);

    que.push(1);
    inQue[1] = true;
    cnt[1]++;

    while(!que.empty()){
        cur = que.front();
        inQue[cur] = false;
        que.pop();
        for(i = 1; i <= nodeNum; i++){
            if(dist[i] > dist[cur] + graph[cur][i]){
                dist[i] = dist[cur] + graph[cur][i];
                if(cnt[i] > nodeNum-1)
                    return false;
                if(!inQue[i]){
                    que.push(i);
                    inQue[i] = true;
                    cnt[i]++;
                }
            }
        }
    }

    return true;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    int test, i, j, S, E, weight;

    cin>>test;
    while(test--){
        cin>>nodeNum>>PedgeNum>>NedgeNum;

        initGraph();
        for(i = 0; i < PedgeNum; i++){
            cin>>S>>E>>weight;
            if(graph[S][E] > weight){
                graph[S][E] = weight;
                graph[E][S] = weight;
            }
        }

        for(i = 0; i < NedgeNum; i++){
            cin>>S>>E>>weight;
            graph[S][E] = -weight;
        }

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

bellman_Ford:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;

const int MAX_SIZE = 520,
          INF = 1<<29,
          MOD = 1000000007;

//PedgeNum 表示正边数,NedgeNum表示负边数
int nodeNum, PedgeNum, NedgeNum, edgeNum;
struct Edge
{
    int S, E, weight;
};

Edge edge[MAX_SIZE*MAX_SIZE];

//有负环返回 false, 否则返回 true
bool bellman_Ford()
{
    int dist[MAX_SIZE], i, j, flag;
    for(i = 1; i <= nodeNum; i++)
        dist[i] = (1 == i? 0:INF);

    for(i = 1; i < nodeNum; i++){
        flag = false;
        for(j = 0; j < edgeNum; j++)
            if(dist[edge[j].E] > dist[edge[j].S] + edge[j].weight){
                dist[edge[j].E] = dist[edge[j].S] + edge[j].weight;
                flag = true;
            }
        if(!flag)
            return true;
        //正常情况下这里只是 break 但是这里只要判断负环,可直接返回
    }

    for(j = 0; j < edgeNum; j++)
        if(dist[edge[j].E] > dist[edge[j].S] + edge[j].weight)
            return false;

    return true;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    int test, i, j, S, E, weight;

    cin>>test;
    while(test--){
        cin>>nodeNum>>PedgeNum>>NedgeNum;

        edgeNum = 0;
        for(i = 0; i < PedgeNum; i++){
            cin>>S>>E>>weight;
            edge[edgeNum].S = edge[edgeNum + 1].E = S;
            edge[edgeNum].E = edge[edgeNum + 1].S = E;
            edge[edgeNum].weight = edge[edgeNum + 1].weight = weight;
            edgeNum += 2;
        }

        for(i = 0; i < NedgeNum; i++){
            cin>>S>>E>>weight;
            edge[edgeNum].S = S;
            edge[edgeNum].E = E;
            edge[edgeNum].weight = - weight;
            edgeNum++;
        }

        if(bellman_Ford())
            cout<<"NO\n";
        else
            cout<<"YES\n";
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值