【spfa】——poj1874——模板*2

                                             Wormholes

Time Limit: 2000MS

 

Memory Limit: 65536K

Total Submissions: 44709

 

Accepted: 16453

Description

While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of FJ's farms comprises N (1 ≤ N ≤ 500) fields conveniently numbered 1..NM (1 ≤ M ≤ 2500) paths, and W (1 ≤W ≤ 200) wormholes.

As FJ is an avid time-traveling fan, he wants to do the following: start at some field, travel through some paths and wormholes, and return to the starting field a time before his initial departure. Perhaps he will be able to meet himself :) .

To help FJ find out whether this is possible or not, he will supply you with complete maps to F (1 ≤ F ≤ 5) of his farms. No paths will take longer than 10,000 seconds to travel and no wormhole can bring FJ back in time by more than 10,000 seconds.

Input

Line 1: A single integer, FF farm descriptions follow. 
Line 1 of each farm: Three space-separated integers respectively: NM, and W 
Lines 2..M+1 of each farm: Three space-separated numbers (SET) that describe, respectively: a bidirectional path between S and E that requires T seconds to traverse. Two fields might be connected by more than one path. 
Lines M+2..M+W+1 of each farm: Three space-separated numbers (SET) that describe, respectively: A one way path from S to E that also moves the traveler back T seconds.

Output

Lines 1..F: For each farm, output "YES" if FJ can achieve his goal, otherwise output "NO" (do not include the quotes).

Sample Input

2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8

Sample Output

NO
YES

Hint

For farm 1, FJ cannot travel back in time. 
For farm 2, FJ could travel back in time by the cycle 1->2->3->1, arriving back at his starting location 1 second before he leaves. He could start from anywhere on the cycle to accomplish this.
 
题意:

要求判断任意两点都能仅通过正边就互相可达的有向图(图中有 重边)中是否存在负权环

 
代码一:(北大模板)
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;

int F,N,M,W;
const int INF = 1 << 30;

struct Edge {
         int e,w;
         Edge(int ee,int ww):e(ee),w(ww) { }
         Edge() { }
};

vector<Edge> G[1000]; //整个有向图

int updateTimes[1000]; //最短路的改进次数

int dist[1000]; //dist[i]是源到i的目前最短路长度

int Spfa(int v)
{
        for( int i = 1; i <= N; ++i)
                dist[i] = INF;
        dist[v] = 0;

        queue<int> que;

        que.push(v);

        memset(updateTimes ,0,sizeof(updateTimes));

        while( !que.empty())
        {
                 int s = que.front();
                que.pop();

                 for( int i = 0;i < G[s].size(); ++i)
                 {
                         int e = G[s][i].e;
                         if( dist[e] > dist[s] + G[s][i].w )
                         {
                                 dist[e] = dist[s] + G[s][i].w;
                                 que.push(e); //没判队列里是否已经有e,可能会慢一些
                                 ++updateTimes[e];
                                 if( updateTimes[e] >= N)//某一条边可找到大于 n 次的更小路径值
                                    return true;
                         }
                 }
        }
        return false;
}

int main()
{
        cin >> F;
        while( F--)
        {
                 cin >> N >> M >> W;
                 for( int i = 1; i <1000; ++i)
                         G[i].clear();

                 int s,e,t;
                 for( int i = 0; i < M; ++ i)
                 {
                          cin >> s >> e >> t;
                         G[s].push_back(Edge(e,t));
                         G[e].push_back(Edge(s,t));
                 }
                 for( int i = 0;i < W; ++i)
                 {
                          cin >> s >> e >> t;
                         G[s].push_back(Edge(e,-t));//虫洞看做负权边
                 }

                 if( Spfa(1))
                        cout << "YES" <<endl;
                 else
                        cout << "NO" <<endl;
         }
}

 

代码二:(上交模板)
 
 
#include<iostream>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;

vector<pair<int,int> >g[3000];
queue<int>que;

int n,m,src,w;

int dist[3000];
bool inQue[3000];
int uptime[3000];

int flag;

void spfa()
{
    memset(dist,0x3f3f3f3f,sizeof(dist));
    memset(uptime,0,sizeof(uptime));
    memset(inQue,false,sizeof(inQue));
    dist[src]=0;

    while(!que.empty())que.pop();

    que.push(src);

    inQue[src]=true;

    while(!que.empty())
    {
        int u=que.front();
        que.pop();

        for(int i=0;i<g[u].size();i++)
        {
            if(dist[u]+g[u][i].second<dist[g[u][i].first])
            {
                dist[g[u][i].first]=dist[u]+g[u][i].second;

                if(!inQue[g[u][i].first])
                {
                    inQue[g[u][i].first]=true;
                    que.push(g[u][i].first);
                    ++uptime[g[u][i].first];
                    if(uptime[g[u][i].first]>=n)
                    {
                        flag=1;
                        return ;
                    }
                }
            }
        }
        inQue[u]=false;
    }
}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m>>w;
        flag=0;

        for(int i=1;i<3000;i++)
            g[i].clear();

        int s,e,t;
        for(int i=0;i<m;i++)
        {
            cin>>s>>e>>t;
            g[s].push_back(make_pair(e,t));
            g[e].push_back(make_pair(s,t));
        }
        for(int i=0;i<w;i++)
        {
            cin>>s>>e>>t;
            g[s].push_back(make_pair(e,-t));
        }

        src=1;
        spfa();

        if(flag==1)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;

    }
    return 0;
}

 

posted @ 2016-08-29 14:06  琥珀川||雨露晨曦  阅读(93)  评论(0编辑  收藏  举报