Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 44248 | Accepted: 16280 |
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..N, M (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 of each farm: Three space-separated integers respectively: N, M, and W
Lines 2.. M+1 of each farm: Three space-separated numbers ( S, E, T) 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 ( S, E, T) that describe, respectively: A one way path from S to E that also moves the traveler back T seconds.
Output
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 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.
Source
题目意思:
解题思路:
①SPFA
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <iomanip>
#include <algorithm>
#define MAXN 10010
#define INF 0xfffffff
using namespace std;
struct ArcNode
{
int to;
int weight;
ArcNode *next;
};
queue<int> Q;//队列中的节点为顶点序号
int n;//顶点个数
int m,W;
ArcNode * List[MAXN];//每个顶点的边链表表头指针
int inq[MAXN];//每个顶点是否在队列中的标志
int dist[MAXN],path[MAXN];
int cnt[MAXN];
bool SPFA(int src)
{
memset(cnt,0,sizeof(cnt));
memset(inq,0,sizeof(inq));
int i,u;//u为队列头顶点序号
ArcNode * temp;
for(i=1; i<=n; ++i)//初始化
{
dist[i]=INF;
path[i]=src;
inq[i]=0;
}
dist[src]=0;
path[src]=src;
++inq[src];
Q.push(src);
++cnt[src];
while(!Q.empty())
{
u=Q.front();
Q.pop();
--inq[u];
if(cnt[u]>n) return true;//存在负权回路
temp=List[u];
while(temp!=NULL)
{
int v=temp->to;
if(dist[v]>dist[u]+temp->weight)
{
dist[v]=dist[u]+temp->weight;
path[v]=u;
if(!inq[v])
{
Q.push(v);
++inq[v];
++cnt[v];
}
}
temp=temp->next;
}
}
return false;
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("G:/x/read.txt","r",stdin);
freopen("G:/x/out.txt","w",stdout);
#endif
int i,t;
cin>>t;
while(t--)
{
int u,v,w;
cin>>n>>m>>W;
memset(List,0,sizeof(List));
ArcNode *temp;
while(!Q.empty()) Q.pop();
while(m--)
{
cin>>u>>v>>w;
temp=new ArcNode;
temp->to=v;//构造邻接表
temp->weight=w;
temp->next=NULL;
if(List[u]==NULL) List[u]=temp;
else
{
temp->next=List[u];
List[u]=temp;
}
//无向图,构建两条边
temp=new ArcNode;
temp->to=u;//构造邻接表
temp->weight=w;
temp->next=NULL;
if(List[v]==NULL) List[v]=temp;
else
{
temp->next=List[v];
List[v]=temp;
}
}
while(W--)//负权路
{
cin>>u>>v>>w;
temp=new ArcNode;
temp->to=v;//构造邻接表
temp->weight=-w;
temp->next=NULL;
if(List[u]==NULL) List[u]=temp;
else
{
temp->next=List[u];
List[u]=temp;
}
}
if(SPFA(1)) puts("YES");//求源点到其他顶点的最短路径
else puts("NO");
for(i=0; i<=n; ++i)
{
temp=List[i];
while(temp!=NULL)
{
List[i]=temp->next;
delete temp;
temp=List[i];
}
}
}
return 0;
}
/*
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
*/
②Bellman Ford 邻接表
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
using namespace std;
#define INF 0xfffffff
#define MAXN 100010
struct Edge
{
int u,v,w;
};
Edge edge[MAXN];//邻接表
int n,m;//顶点数和边数
int cnt=0;
int dist[MAXN];//顶点s到其他顶点的最短路径、
int Bellman(int s)//顶点s到其他顶点的最短路径
{
int i,j;
for(i=0; i<n; ++i)//初始化
dist[i]=INF;
dist[s]=0;
for(i=1; i<n; ++i)
for(j=0; j<m; ++j)
{
Edge e=edge[j];
if(dist[e.u]!=INF&&e.w+dist[e.u]<dist[e.v])//顶点k到j有直接路径而且途径k可以使得路径缩短
dist[e.v]=e.w+dist[e.u];
}
for(i=0; i<m; ++i)
if(dist[edge[i].u]!=INF&&edge[i].w+dist[edge[i].u]<dist[edge[i].v])
return 1;
return 0;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
cnt=0;
int i,W;
cin>>n>>m>>W;
int u,v,va;
for(i=0; i<m; ++i)
{
cin>>u>>v>>va;
--u,--v;
edge[cnt].u=u,edge[cnt].v=v,edge[cnt++].w=va;
edge[cnt].u=v,edge[cnt].v=u,edge[cnt++].w=va;
}
for(i=0; i<W; ++i)
{
cin>>u>>v>>va;
--u,--v;
edge[cnt].u=u,edge[cnt].v=v,edge[cnt++].w=-va;
}
m=cnt;
if(Bellman(0)) puts("YES");//顶点0到其他顶点的最短路
else puts("NO");
}
return 0;
}
/**
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
**/