poj 3259 Wormholes (spfa判负环)

来源:互联网 发布:新速特软件站最新版 编辑:程序博客网 时间:2024/05/21 07:00

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

题意:农场有n个节点,m条小路,w个虫洞,虫洞可以让自己返回到出发之前的时间(就是负路径),用spfa判断是否有负环,因为一旦出现负环就可以多次重复负环,使得时间会提前很多,这样就一定可以回到出发之前的时间。

注意:小路是双向的,虫洞是单向的;

    注意map是从0开始的;

    注意重边;

#include<cstdio>#include<queue>using namespace std;const int num=505;const int inf=0x3fffffff;//太大会溢出int map[num][num],p[num],n,m,w,flag,dis[num],pn[num];//pn记录入队列的次数,次数大于n则表示出现负环queue <int> q;void init(){    int i,j;    for(i=0;i<n;i++)    {        for(j=0;j<n;j++)            map[i][j]=inf;        p[i]=0;        pn[i]=0;        dis[i]=inf;    }    flag=0;}void spfa(int a){    int i,t;    q.push(a);    p[a]=1;    pn[a]++;    dis[a]=0;    while(!q.empty())    {        t=q.front();        q.pop();        for(i=0;i<n;i++)        {            if(dis[i]>dis[t]+map[t][i])            {                dis[i]=dis[t]+map[t][i];                if(p[i]==0)                {                    p[i]=1;                    q.push(i);                    pn[i]++;                }            }            if(pn[i]>n)            {                flag=1;                break;            }        }        p[t]=0;    }}int main(){    int t,i,a,b,c;    //freopen("in.txt","r",stdin);    scanf("%d",&t);    while(t--)    {        scanf("%d%d%d",&n,&m,&w);        init();        while(!q.empty()) q.pop();        for(i=0;i<m;i++)        {            scanf("%d%d%d",&a,&b,&c);            a--;b--;            if(map[a][b]>c)     //注意重边            {                map[a][b]=c;                map[b][a]=c;            }        }        for(i=0;i<w;i++)        {            scanf("%d%d%d",&a,&b,&c);            a--,b--;            if(map[a][b]>-c)                map[a][b]=-c;        }        spfa(0);        if(flag)            printf("YES\n");        else            printf("NO\n");    }    return 0;}

0 0
原创粉丝点击