POJ 3259:Wormholes

Description

John农夫拥有许多农场,John发现了许多神奇的树洞。这些树洞 都非常特殊因为进入树洞后能够把你送到一个目的地,并且到达目的地时的时间早于你进入树洞时的时间(比如你进入洞时是2000年,但是出洞时发现是1990年)。每个农场都有N(1<=N<=500)个field,记为1...N,M(1<=M<=2500)条path,W(1<=W<=200)个wormhole。
 
John是一个很喜欢穿越的人,他想从某个区域进入,并且经过一系列的路径或树洞 ,最后到达起点,并且到达起点时发现比最初在起点的时间还早。
 
为了帮助John实现这个愿望,他提供给我们他的F(1<=F<=5)个farm的地图。已知穿过每一条path的时间都小于等于10000s,穿过每个树洞所倒退的时间小于等于10000s。

Input

第一行是farm的个数。
第二行是第一个farm的field个数N,path的个数M,树洞的个数W。
第3~M+2 行是 path 的起点、终点、穿越时间(注意,这里的path都是双向边)
第M+3~M+W+2 行是树洞的起点、终点、倒退时间(单向边)
接着是第二个farm。
 

Output

对于每个farm,如果这个farm能够达成目标,则输出“YES”,否则输出“NO"。

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

对于 Sample Input :

farm 1 不能够达到目标。

farm 2 能够,因为 1->2->3->1,他回到1时比原来提前了1秒。

 

算法思想

将field作为节点,path作为正权边,wormholes作为负权边,注意:path是双向边。

第一步:添加一个虚拟源点s,并将这个虚拟源点连向所有的节点(field),因此共有N+1个节点,2*M+W+N条边。

第二步:对虚拟源点s运行Bellman-Ford算法,判断是否有源点可达负圈即可。

 

算法实现

  1   2 

  3 import java.util.Scanner;

  4 

  5 public class Main {

  6     int n;            // 节点个数

  7     int m;            // 边的个数

  8     int head[];        // head[i] 表示节点i指向的第一条边的索引是多少

  9     int edge[][];    // edge[i]表示第i条边 ,edge[i][1]表示这条边的起点,edge[i][2]表示这条边的终点,edge[i][3]表示这条边的权重

 10     int next[];        // next[i]表示第i条边在邻接表中的下一条边是什么

 11     int d[];        // d[i]表示第i条边的d值 

 12     

 13     int farmNumber;

 14     int N[];

 15     int M[];

 16     int W[];

 17     int current_farm = 0;

 18     

 19     public void getSingleFarm(Scanner in){

 20         int current_edge = 0;

 21         N[current_farm] = in.nextInt();

 22         M[current_farm] = in.nextInt();

 23         W[current_farm] = in.nextInt();

 24         this.n = N[current_farm]+1;

 25         this.m = 2*M[current_farm]+W[current_farm]+N[current_farm];

 26         //2*M+W+N条边

 27         head = new int[n];

 28         edge = new int[m][4];

 29         next = new int[m];

 30         d = new int[n];

 31         for(int i=0;i<n;i++){

 32             head[i] = -1;

 33         }

 34         for(int i=1;i<=N[current_farm];i++){

 35             edge[current_edge][1] = 0;

 36             edge[current_edge][2] = i;

 37             edge[current_edge][3] = 0;

 38             next[current_edge] = head[0];

 39             head[0] = current_edge;

 40             current_edge++;

 41         }

 42         for(int i=1;i<=M[current_farm];i++){

 43             int from = in.nextInt();

 44             int to = in.nextInt();

 45             int cost = in.nextInt();

 46             edge[current_edge][1] = from;

 47             edge[current_edge][2] = to;

 48             edge[current_edge][3] = cost;

 49             next[current_edge] = head[from];

 50             head[from] = current_edge;

 51             current_edge++;

 52             

 53             edge[current_edge][1] = to;

 54             edge[current_edge][2] = from;

 55             edge[current_edge][3] = cost;

 56             next[current_edge] = head[to];

 57             head[to] = current_edge;

 58             current_edge++;

 59         }

 60         for(int i=1;i<=W[current_farm];i++){

 61             int from = in.nextInt();

 62             int to = in.nextInt();

 63             int cost = in.nextInt();

 64             edge[current_edge][1] = from;

 65             edge[current_edge][2] = to;

 66             edge[current_edge][3] = -cost;

 67             next[current_edge] = head[from];

 68             head[from] = current_edge;

 69             current_edge++;

 70         }

 71         current_farm++;

 72     }

 73     public void getInput(Scanner in){

 74         

 75         farmNumber = in.nextInt();

 76         N = new int[farmNumber];

 77         M = new int[farmNumber];

 78         W = new int[farmNumber];

 79         

 80         for(int i=1;i<=farmNumber;i++){

 81             getSingleFarm(in);

 82             boolean flag = BellmanFord(0);

 83             if(flag) System.out.println("NO");

 84             else System.out.println("YES");

 85             

 86         }

 87     }

 88     

 89     public boolean BellmanFord(int s){

 90         for(int i=0;i<n;i++){

 91             d[i] = Integer.MAX_VALUE;

 92         }

 93         d[s] = 0;

 94         boolean flag = true;

 95         for(int t=1;t<=n-1;t++){

 96             if(flag){

 97                 flag = false;

 98                 for(int i=0;i<n;i++){

 99                     for(int j=head[i];j!=-1;j=next[j]){

100                         if(d[edge[j][2]]>d[i]+edge[j][3]){

101                             d[edge[j][2]] = d[i] + edge[j][3];

102                             flag = true;

103                         }

104                     }

105                 }

106             }

107         }

108         for(int i=0;i<n;i++){

109             for(int j=head[i];j!=-1;j=next[j]){

110                 if(d[edge[j][2]]>d[i]+edge[j][3]){

111                     return false;

112                 }

113             }

114         }

115         return true;

116     }

117     

118     public static void main(String[] args) {

119         Main main = new Main();

120         main.getInput(new Scanner(System.in));

121         

122     }

123 }

 

 

 

 

你可能感兴趣的:(orm)