zoukankan      html  css  js  c++  java
  • ACM: POJ 3259 Wormholes

     POJ 3259 Wormholes
    Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu
     

    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.. MW+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.
     
    /*/
    这题是判断是否产生了负环。
    
    由于边权出现了负数这个题目就不能用普通的最短路来算,用到Floyd 或者SPFA算法。
    
    由于题目意思要判断是否产生了负环,可以直接用SPFA算法来判断负环。
    
    下面这个SPFA算法,d[n]为终点,如果起点u开始到达不了某个点,那么d等于INF 
    
    如果到达的了,且路上会经过负环,所以到达那个点的时候,最短路会等于-INF
    
    如果到达那个点的时候,是正常到达的,没有经过负环,而且可以到达,那么就是介于两者之间的一个正常的值。
    
    AC代码:
    
    /*/
     
    #include"algorithm"
    #include"iostream"
    #include"cstring"
    #include"cstdlib"
    #include"cstdio"
    #include"string"
    #include"vector"
    #include"queue"
    #include"cmath"
    using namespace std;
    typedef long long LL ;
    #define memset(x,y) memset(x,y,sizeof(x))
    #define memcpy(x,y) memcpy(x,y,sizeof(x))
    #define FK(x) cout<<"["<<x<<"]
    "
    #define bigfor(x) for(int qq=1;qq<= T ;qq++)
    
    const int spfa_v=10005;
    const int spfa_edge=10005;
    
    template <class T>
    struct SPFA {
    
    	struct Edge {
    		int v,nxt;
    		T w;
    	} E[spfa_edge<<1];
    
    	int Head[spfa_v],erear;
    
    	T p[spfa_v],INF;
    
    	typedef pair< T , int > PII;
    
    	void edge_init() {
    		memset(Head,-1);
    		memset(E,0);
    		memset(dis,0);
    		erear=0;
    	}
    
    	void edge_add(int u,int v,T w) {
    		E[erear].v=v;
    		E[erear].w=w;
    		E[erear].nxt=Head[u];
    		Head[u]=erear++;
    	}
    
    	bool dis[spfa_edge];
    	bool vis[spfa_edge];
    	int flag[spfa_edge];
    
    	void init() {
    		memset(vis,0);
    		memset(p,0x3f);
    		memset(flag,0);
    		memset(dis,0);
    		INF=p[0];
    	}
    
    	void run(int u,int n) { //u为起点
    		init();
    		queue<int > Q;
    		while(!Q.empty())Q.pop();
    		p[u]=0;
    		Q.push(u);
    		while(!Q.empty()) {
    			int a=Q.front();
    			Q.pop();
    			vis[a]=0,dis[a]=1;
    			for(int i=Head[a]; ~i; i=E[i].nxt) {
    				int v=E[i].v;
    				T   w=E[i].w;
    				int s = p[a] == -INF?-INF:w+p[a];  //如果已经是负环了,后面的也赋值-INF
    				if(s<p[v]) {
    					p[v]=s;
    					if(!vis[v]) {  //判断是否已经走过这条边了。
    						vis[v]=1;
    						flag[v]++;
    						if(flag[v]>n)p[v]=-INF; //如果超过n次则说明已经形成了负环,值赋为-INF
    						Q.push(v);
    					}
    				}
    			}
    		}
    	}
    };
    SPFA<int > sp;
    
    
    int main() {
    	int T;
    	int n,m,k,u,v,w;
    	while(~scanf("%d",&T)) {
    		bigfor(T) {
    			sp.edge_init();
    			int sign=0;
    			scanf("%d%d%d",&n,&m,&k);
    			for(int i=0; i<m; i++) {
    				scanf("%d%d%d",&u,&v,&w);
    				sp.edge_add(u,v,w);
    				sp.edge_add(v,u,w);
    			}
    			for(int i=0; i<k; i++) {
    				scanf("%d%d%d",&u,&v,&w);
    				sp.edge_add(u,v,-w);
    			}
    			for(int i=1; i<=n; i++) {
    				if(sp.dis[i])continue; //如果这个点已经查过那就不需要再查。
    				sp.run(i,n);
    				if(sp.p[i]<0) {//产生了负环sp.p[i]的值才可能为负 而且是 -INF 
    sign=1;break; } } printf("%s ",sign?"YES":"NO") ; } } return 0; }

      

     
  • 相关阅读:
    position笔记
    IFE-33笔记
    IFE-31 笔记
    selectedIndex
    iFE-30 笔记
    基于select的python聊天室程序
    python select网络编程详细介绍
    (转载)centos yum源的配置和使用
    python 多进程使用总结
    python迭代器实现斐波拉契求值
  • 原文地址:https://www.cnblogs.com/HDMaxfun/p/5762991.html
Copyright © 2011-2022 走看看