蟲洞

題目描述

John 在他的農場中閒逛時發現了許多蟲洞。蟲洞能夠看做一條十分奇特的有向邊,並可使你返回到過去的一個時刻(相對你進入蟲洞以前)。John 的每一個農場有 M條小路(無向邊)鏈接着 N從 1到 N標號)塊地,並有 W個蟲洞。如今 John 想借助這些蟲洞來回到過去(在出發時刻以前回到出發點),請你告訴他能辦到嗎。 John 將向你提供F 個農場的地圖。沒有小路會耗費你超過 10^4 的時間,固然也沒有蟲洞回幫你回到超過 10^4秒之前。ios

輸入

第一行一個整數F表示農場個數;對於每一個農場:第一行,三個整數 N,M,W;接下來 M行,每行三個數 S,E,T 表示在標號爲 S的地與標號爲 E的地中間有一條用時 T秒的小路;接下來 W行,每行三個數 S,E,T 表示在標號爲 S的地與標號爲 E的地中間有一條可使 John 到達 T秒前的蟲洞。數組

輸出

輸出共 F行,若是 John 能在第 I個農場實現他的目標,就在第 I行輸出 YES,不然輸出 NO。測試

數據範圍限制

對於所有數據:
1<=F<=5
1<=N<=500
1<=M<=2500
1<=W<=200
1<=S,E<=N
|T|<=10^4spa

迷人吶。code

這道題一看其實就有思路了,由於他給咱們一些富有魅力的詞彙:「有向邊」 「有M條小路(無向邊)」。因而咱們不難想到最短路求解。
我一開始想要的是dijkstra,緣由是被樣例給迷惑了,其實他並無說蟲洞是從哪到哪,而樣例都是從終點到第一個點。隊列

咱們不難看出路是雙向的,而蟲洞只有單向且權值爲負。題目中:「如今 John 想借助這些蟲洞來回到過去(在出發時刻以前回到出發點)」的意義就是說若是一號點到一號點的最短路爲負,那麼輸出YES。而後剛看題意時我還很懵(´・ω・`)(不知道農場是啥),後來才發現一個農場至關於一組測試數據string

比賽交了兩次,而後竟沒AC——第一次visit數組(v數組,記錄是否在隊列中)過小,我把它開大了。而後75分,俺含着淚看了代碼,鏈式前向星開小了(雙向邊×2)(┳_┳)...。it

好了,裸的負迴路SPFA。
代碼:io

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
int n,m,w;
struct edge{
    int x;//起點
    int y;//終點
    int val;//權值
    int last;//以x爲起點的上一條路在e(鏈式前向星)中的位置
}e[6000];
int head[2000];//head[i]表示以i爲起點的最後一條路在e中的位置
int cnt;//道路數量

int dis[2000];//記錄最短路
int v[2000];//是否在隊列中
queue<int> q;//隊列

void add(int a, int b, int v)//記錄道路和蟲洞(鏈式前向星)
{
    ++cnt;
    e[cnt].x = a;
    e[cnt].y = b;
    e[cnt].val = v;
    e[cnt].last = head[a];
    head[a] = cnt;
}

void spfa()
{
    memset(dis,0x3f3f3f3f,sizeof(dis));
    memset(v,0,sizeof(v));
    
    dis[1] = 0;
    q.push(1);//1進隊列
    v[1] = 1;
    
    while(!q.empty())
    {
        if(dis[1] < 0)
            return;
        int r = q.front();
        for(int i = head[r]; i != 0; i = e[i].last)
        {
            int k = e[i].y;
            if(dis[r] + e[i].val < dis[k])
            {
                dis[k] = dis[r] + e[i].val;
                if(v[k] == 0)//當k不在隊列中(差點忘記呀)
                {
                    q.push(k);
                    v[k] = 1;
                }
            }
        }
        q.pop();
        v[r] = 0;
    }
}

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        cnt = 0;
        memset(e,0,sizeof(e));
        memset(head,0,sizeof(head));
        scanf("%d%d%d", &n, &m, &w);
        for(int i = 1; i <= m; i++)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            add(a, b, c);
            add(b, a, c);
        }
        for(int i = 1; i <= w; i++)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            add(a, b, -c);//只記錄一次
        }
        spfa();
//      for(int i = 1; i <= n; i++)//測試不用管
//          printf("%d\n",dis[i]);//測試不用管 + 1
        if(dis[1] < 0)
            printf("YES");
        else
            printf("NO");
        printf("\n");
    }
        return 0;
}
相關文章
相關標籤/搜索