您的位置:首页 > 其它

Wormholes

2015-08-24 11:24 429 查看
Description

Whileexploringhismanyfarms,FarmerJohnhasdiscoveredanumberofamazingwormholes.Awormholeisverypeculiarbecauseitisaone-waypaththatdeliversyoutoitsdestinationatatimethatisBEFOREyouenteredthe
wormhole!EachofFJ'sfarmscomprisesN(1≤N≤500)fieldsconvenientlynumbered1..N,
M(1≤M≤2500)paths,andW(1≤W≤200)wormholes.

AsFJisanavidtime-travelingfan,hewantstodothefollowing:startatsomefield,travelthroughsomepathsandwormholes,andreturntothestartingfieldatimebeforehisinitialdeparture.Perhapshewillbeableto
meethimself:).

TohelpFJfindoutwhetherthisispossibleornot,hewillsupplyyouwithcompletemapsto
F(1≤F≤5)ofhisfarms.Nopathswilltakelongerthan10,000secondstotravelandnowormholecanbringFJbackintimebymorethan10,000seconds.

Input
Line1:Asingleinteger,
F.Ffarmdescriptionsfollow.

Line1ofeachfarm:Threespace-separatedintegersrespectively:N,
M,andW

Lines2..M+1ofeachfarm:Threespace-separatednumbers(S,
E,T)thatdescribe,respectively:abidirectionalpathbetween
SandEthatrequiresTsecondstotraverse.Twofieldsmightbeconnectedbymorethanonepath.

LinesM+2..M+W+1ofeachfarm:Threespace-separatednumbers(S,
E,T)thatdescribe,respectively:AonewaypathfromSto
EthatalsomovesthetravelerbackTseconds.
Output
Lines1..F:Foreachfarm,output"YES"ifFJcanachievehisgoal,otherwiseoutput"NO"(donotincludethequotes).
SampleInput
2
331
122
134
231
313
321
123
234
318

SampleOutput
NO
YES

题目大意:一个famer有一些农场,这些农场里面有一些田地,田地里面有一些虫洞,田地和田地之间有路,走一条路有时
间花费,虫洞有这样的性质:时间倒流。如果你走的是虫洞路径,那么时间花费为负值,问你这个农民找出一条路径能看到
他自己,也就是说,有没有这样一条路径,能利用虫洞的时间倒流的性质,让这个人能在这个点出发前回去,这样他就是能看
到他自己了。


解题思路:利用SPFA算法判断是否有负环,判断依据就是,一个点入队的次数>=n的话,那就是存在负环
注意:该题中path是双向的,权值是正数。虫洞是单向的,权值是负数。
题意:有n个地点,编号1到n。有m行S,E,T。表示从地点S(E)到地点E(S)的时间为T。
有w个虫洞,通过虫洞可以从S穿越到到E(单向穿越),且时间回到T秒前。问是否存在从一点出发,
回到这一点看到从前的自己。





#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
#defineINF0x3f3f3f
#defineMAX1000
usingnamespacestd;
intd[MAX],mark[MAX],head[MAX],used[MAX];
intedgenum,flag;
intF;//农场的个数,即测试案例的个数
intn,m,w;//n是点的个数,m是道路的条数,w是虫洞
structEdge
{
intfrom,to,val,next;//起点,终点,权值
}edge[MAX*10];
voidaddedge(intu,intv,intw)
{
EdgeE={u,v,w,head[u]};//这样写比较方便,不用逐个赋值。
edge[edgenum]=E;
head[u]=edgenum++;
}
voidSPFA(intsx)
{
memset(d,INF,sizeof(d));
memset(mark,0,sizeof(mark));
memset(used,0,sizeof(used));//有关这个函数的初始化,最好写在这个函数内,因为多次调用这个函数时,每次用前,都要初始化!
queue<int>q;
q.push(sx);//进队列
mark[sx]=1;//标记
d[sx]=0;//sx是源点,自己到自己的距离为0.
used[sx]++;
while(!q.empty())
{
intu=q.front();//取队首元素
q.pop();//出队列
mark[u]=0;//取消标记。
for(inti=head[u];i!=-1;i=edge[i].next)
{
intv=edge[i].to;
if(d[v]>d[u]+edge[i].val)//如果v直接到源点的距离大于v通过u到达源点的距离,那么就更新。
{
d[v]=d[u]+edge[i].val;
if(mark[v]==0)//如果v没有进队列,就让v进队列。
{
q.push(v);
mark[v]=1;
used[v]++;//记录v进队列的次数
if(used[v]>n)//进队列的次数大于n时,说明图中有负环!
{
printf("YES\n");
return;
}

}
}
}

}
printf("NO\n");
}
intmain()
{
inta,b,c,f,g,h;
scanf("%d",&F);
while(F--)
{
flag=0;
memset(head,-1,sizeof(head));//初始化
edgenum=0;
scanf("%d%d%d",&n,&m,&w);
while(m--)
{
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);//无向图建图要建双向边
addedge(b,a,c);
}
while(w--)
{
scanf("%d%d%d",&f,&g,&h);
addedge(f,g,-h);//虫洞是单向的,权值为负!!!
}
SPFA(1);
}
return0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: