Problem:
Problem C:
Magical Dungeon
Arthur C. Malory is a wandering valiant fighter (in a game world).
One day, he visited a small village and stayed overnight. Next morning, the village mayor called on him. The
mayor said a monster threatened the village and requested him to defeat it. He was so kind that he decided to
help saving the village.
The mayor told him that the monster seemed to come from the west. So he walked through a forest swept away
in the west of the village and found a suspicious cave. Surprisingly, there was a deep dungeon in the cave. He
got sure this cave was the lair of the monster.
Fortunately, at the entry, he got a map of the dungeon. According to the map, the monster dwells in the depth of
the dungeon. There are many rooms connected by paths in the dungeon. All paths are one-way and filled with
magical power. The magical power heals or damages him when he passes a path.
The amount of damage he can take is indicated by hit points. He has his maximal hit points at the beginning and
he goes dead if he lost all his hit points. Of course, the dead cannot move nor fight - his death means the failure
of his mission. On the other hand, he can regain his hit points up to his maximal by passing healing paths. The
amount he gets healed or damaged is shown in the map.
Now, he wants to fight the monster with the best possible condition. Your job is to maximize his hit points when
he enters the monster’s room. Note that he must fight with the monster once he arrives there. You needn’t care
how to return because he has a magic scroll to escape from a dungeon.
Input
The input consists of multiple test cases.
The first line of each test case contains two integers
N
(2 ≤
N
≤ 100) and
M
(1 ≤
M
≤ 1000).
N
denotes the
number of rooms and
M
denotes the number of paths. Rooms are labeled from 0 to
N
- 1. Each of next
M
lines
contains three integers
f
i
,
t
i
and
w
i
(|
w
i
| ≤ 10
7
), which describe a path connecting rooms.
f
i
and
t
i
indicate the
rooms connected with the entrance and exit of the path, respectively. And
w
i
indicates the effect on Arthur’s hit
points; he regains his hit points if
w
i
is positive; he loses them otherwise. The last line of the case contains three
integers
s
,
t
and
H
(0 <
H
≤ 10
7
).
s
indicates the entrance room of the dungeon,
t
indicates the monster’s room
and
H
indicates Arthur’s maximal hit points. You can assume that
s
and
t
are different, but
f
i
and
t
i
may be the same.
The last test case is followed by a line containing two zeroes.
Output
For each test case, print a line containing the test case number (beginning with 1) followed by the maximum
possible hit points of Arthur at the monster’s room. If he cannot fight with the monster, print the case number
and “GAME OVER” instead.
Sample Input
7 8
0 2 3
2 3 -20
3 4 3
4 1 -5
1 5 1
5 4 5
1 3 2
3 6 -2
0 6 30
7 8
0 2 3
2 3 -20
3 4 3
4 1 -5
1 5 1
5 4 5
1 3 2
3 6 -2
0 6 20
4 4
0 1 -10
1 2 -50
2 1 51
1 3 1
0 3 20
11 14
0 1 -49
1 2 1
2 3 40
3 1 -40
1 4 -9
4 5 40
5 1 -30
...(truncated)

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 105

struct Edge{
	Edge(int arg_to,ll arg_dist){
		to = arg_to;
		dist = arg_dist;
	}
	int to;
	ll dist;
};

struct Info{
	Info(int arg_from,int arg_to,ll arg_dist){
		from = arg_from;
		to = arg_to;
		dist = arg_dist;
	}

	int from,to;
	ll dist;
};


int N,M,num_case;
int start,goal;
int pre_node[SIZE];
bool is_inf[SIZE],visited[SIZE];
ll MAX;
ll dp[SIZE],work[SIZE];
ll add_hp[SIZE][SIZE];
vector<Edge> G[SIZE];
vector<Info> info;

bool calc(int edge_id){

	dp[info[edge_id].to] = min(MAX,dp[info[edge_id].from]+info[edge_id].dist);
	pre_node[info[edge_id].to] = info[edge_id].from;

	vector<int> vec;
	vec.push_back(info[edge_id].to);

	for(int i = 0; i < N; i++){

		visited[i] = false;
	}

	int current = info[edge_id].to,pre;
	visited[current] = true;

	while(true){

		pre = pre_node[current];
		if(pre == -1){

			return true;
		}
		if(visited[pre])break;
		visited[pre] = true;
		vec.push_back(pre);

		current = pre;
	}

	if(pre != info[edge_id].to)return true;

	for(int i = 0; i < N; i++){

		work[i] = -HUGE_NUM;
	}

	ll tmp = dp[vec[0]];
	work[vec[0]] = tmp;
	ll maximum = tmp;

	reverse(vec.begin(),vec.end());

	for(int i = 0; i < vec.size()-1; i++){

		tmp += add_hp[vec[i]][vec[i+1]];
		if(tmp > MAX){

			tmp = MAX;
		}
		maximum = max(maximum,tmp);
		work[vec[i+1]] = tmp;
	}

	for(int i = 0; i < vec.size(); i++){

		if(work[vec[i]] == maximum){

			dp[vec[i]] = MAX;
		}
	}

	return true;
}

void func(){

	info.clear();

	for(int i = 0; i < N; i++){
		G[i].clear();
	}

	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){

			add_hp[i][k] = -HUGE_NUM;
		}
	}

	int from,to;
	ll dist;

	for(int i = 0; i < M; i++){

		scanf("%d %d %lld",&from,&to,&dist);
		add_hp[from][to] = max(add_hp[from][to],dist);
	}

	scanf("%d %d %lld",&start,&goal,&MAX);

	for(int from = 0; from < N; from++){
		if(from == goal)continue;
		for(int to = 0; to < N; to++){
			if(add_hp[from][to] == -HUGE_NUM)continue;

			G[from].push_back(Edge(to,add_hp[from][to]));
			info.push_back(Info(from,to,add_hp[from][to]));
		}
	}

	for(int i = 0; i < N; i++){

		dp[i] = -HUGE_NUM;
		pre_node[i] = -1;
	}
	dp[start] = MAX;

	bool FLG = true;

	while(FLG){

		FLG = false;

		for(int i = 0; i < info.size(); i++){
			if(dp[info[i].from] <= 0 || dp[info[i].from]+info[i].dist <= 0 ||
					min(MAX,dp[info[i].from]+info[i].dist) <= dp[info[i].to])continue;

			FLG |= calc(i);
		}

		if(!FLG)break;
	}


	printf("Case %d: ",num_case);

	if(dp[goal] == -HUGE_NUM){

		printf("GAME OVER\n");

	}else{

		printf("%lld\n",dp[goal]);
	}
}

int main(){

	num_case = 1;

	while(true){

		scanf("%d %d",&N,&M);
		if(N == 0 && M == 0)break;

		func();
		num_case++;
	}

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3308
final_rank: 7

code_snippet: #include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define repr(i, n) for (int i = (n); i >= 0; --i)
#define FOR(i, m, n) for (int i = (m); i < (n); ++i)
#define FORR(i, m, n) for (int i = (m); i >= (n); --i)
#define equals(a, b) (fabs((a) - (b)) < EPS)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const ll mod = 1000000007;
//const ll mod = 998244353;
const int inf = 1e9 + 10;
const ll INF = 1e18;
const ld EPS = 1e-10;
const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }

struct Edge {
  int f, t, c;
};

int Case = 0;
int n, m;
vector<Edge> G;
int s, t, h;
int d[105];
bool isroop[105];

void init() {
  G.clear();
  memset(d, 0, sizeof(d));
  memset(isroop, 0, sizeof(isroop));
}

bool check(int res) {
  memset(d, 0, sizeof(d));
  rep(i, m) {
    int v = G[i].f, u = G[i].t, c = G[i].c;
    if (v != res) continue;
    chmax(d[u], min(h, h + c));
  }
  rep(i, n - 1) {
    rep(j, m) {
      int v = G[j].f, u = G[j].t, c = G[j].c;
      if (!d[v]) continue;
      chmax(d[u], min(h, d[v] + c));
    }
  }
  return d[res] == h;
}

void solve() {
  rep(i, n) isroop[i] = check(i);
  memset(d, 0, sizeof(d));
  d[s] = h;
  rep(i, n - 1) {
    rep(j, m) {
      int v = G[j].f, u = G[j].t, c = G[j].c;
      if (!d[v]) continue;
      chmax(d[u], min(h, d[v] + c));
    }
    rep(j, m) {
      int v = G[j].f, u = G[j].t, c = G[j].c;
      if (!d[v]) continue;
      if (d[u] != min(h, d[v]) && isroop[u]) d[u] = h;
    }
  }
  cout << "Case " << Case << ": ";
  if (d[t]) cout << d[t];
  else cout << "GAME OVER";
  cout << '\n';
}

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout << fixed << setprecision(25);

  while (cin >> n >> m, n) {
    init();
    Case++;
    vector<Edge> tmp;
    rep(i, m) {
      int v, u, w;
      cin >> v >> u >> w;
      tmp.push_back({v, u, w});
    }
    cin >> s >> t >> h;
    for (Edge e: tmp) {
      if (e.f != t) G.push_back(e);
    }

    solve();
  }

  




  
  return 0;
}
accuracy: 1
time_ms: 320
memory_kb: 3156
final_rank: 10

code_snippet: #include<iostream>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
#include<utility>
using namespace std;

int main(){
    int N, M;
    for(int tc=1;1;++tc){
        cin>>N>>M;
        if(!N) return 0;

        // Nが小さいため、ここで定義してむ構わない
        int s,t,H;
        int least[110]={0,}; //least damage
        int checked[110]={0,};
        vector<int> next_room[110], w[110];
        map<int,int> edge_to_boss;

        while(M--){
            int fi,ti,wi;
            cin>>fi>>ti>>wi;

            next_room[fi].push_back(ti);
            w[fi].push_back(-wi);
        }
        cin>>s>>t>>H;

        // init
        for(int i=0;i<N;++i){
            least[i] = H;
        }
        least[s] = 0;

        checked[t] = 1;

        // memorize the edges to boss room
        for(int here=0;here<N;++here){
            if(here==t) continue;
            for(int j=0;j<next_room[here].size();++j){
                int next = next_room[here][j];
                int eff = w[here][j];

                if(next == t){
                    if(edge_to_boss.find(here) == edge_to_boss.end()){
                        edge_to_boss[here] = eff;
                    }
                    else{
                        edge_to_boss[here] = min(edge_to_boss[here],eff);
                    }
                }
            }
        }

        int source = s;
        for(int cnt1=1; cnt1<N;++cnt1){ // 1サイクル当たり頂点1つが無視されるので、N-1回で十分
            //least[source] == 0, checked[source] == 0

            int g = N; //次の始点(距離ゼロの頂点)が決まったらすぐ移行する

            for(int j=0;j<next_room[source].size();++j){
                int adj = next_room[source][j], eff = max(0,w[source][j]);
                if(checked[adj] || adj==source) continue;

                least[adj] = min(least[adj], eff);
                if(least[adj]==0){
                    g = adj;
                }

            }
            checked[source] = 1; //delete(ignore) room 'source'

            if(g < N){
                source = g;
                continue;
            }

            //Bellman-Ford
            for(int cnt2=N-cnt1+1; cnt2; --cnt2){
                //relaxation
                for(int fi=0;fi<N;++fi){
                    if(checked[fi]) continue; //skip ignored
                    if(least[fi]>=H) continue; //skip unreachable rooms
                    for(int j=0;j<next_room[fi].size();++j){
                        int ti = next_room[fi][j], wi = w[fi][j];
                        if(checked[ti]) continue;

                        least[ti] = min(least[ti],max(0,least[fi]+wi));
                        if(least[ti]==0){
                            g = ti; break;
                        }
                    }
                    if(g<N) break;
                }
                if(g<N) break;
            }
            if(g < N){
                source = g;
                continue;
            }

            //処理すべき回路はあるか？
            int p = N;
            for(int fi=0;fi<N;++fi){
                if(checked[fi]) continue;
                if(least[fi]>=H) continue; //skip unreachable rooms
                for(int j=0;j<next_room[fi].size();++j){
                    int ti = next_room[fi][j], wi = w[fi][j];
                    if(checked[ti]) continue;

                    //辺 fi->tiを含む回路でより短くできる
                    if(0>least[fi]+wi){
                        least[ti] = 0;
                        g = ti; break;
                    }
                    if(least[ti] > least[fi]+wi){
                        p = ti; break;
                    }
                }
                if(g<N || p<N) break;
            }
            if(g < N){
                source = g;
                continue;
            }

            //処理すべき負回路はない。
            if(p == N){
                break;
            }

            //pから行けるところ全探索
            int reach[110]={0,},score[110]={0,},minscore = 0;
            g = p;
            queue<int> Q;
            Q.push(p);
            while(!Q.empty()){
                int now = Q.front();
                reach[now] = 1;
                for(int j=0;j<next_room[now].size();++j){
                    int next = next_room[now][j];
                    if(checked[next] || reach[next]) continue;

                    score[next] = score[now] + w[now][j];
                    if(minscore>score[next]){
                        minscore=score[next];
                        g = next;
                    }
                    Q.push(next);
                }
                Q.pop();
            }

            least[g] = 0;
            source = g;
        }

        for(int i=0;i<N;++i){
            if(i == t || least[i] == H || edge_to_boss.find(i) == edge_to_boss.end()) continue;
            least[t] = min(least[t],max(0,least[i]+edge_to_boss[i]));
        }

        cout<<"Case "<<tc<<": ";
        if(least[t] >= H){
            cout << "GAME OVER" << endl;
        }
        else{
            cout << (H-least[t]) << endl;
        }
    }
}
accuracy: 1
time_ms: 50
memory_kb: 3204
final_rank: 6

code_snippet: #include<bits/stdc++.h>
 
#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
 
using namespace std;
 
struct Edge { int dst,w; };
 
const int MAX = 110;
int V,E,sp,ep,iHIT;
vector<Edge> G[MAX];
int maxi[MAX];
 
 
void compute(){
  bool update = true;
  rep(i,V) maxi[i] = 0;
  vector<int> gotoMaxi,candidate;
  gotoMaxi.push_back(sp);
  while( update ) {
    update = false;
    rep(i,(int)gotoMaxi.size()) maxi[gotoMaxi[i]] = iHIT;
    gotoMaxi.clear();
    candidate.clear();

    rep(i,V*3+1) {
      rep(j,V) if( j != ep && maxi[j] ) {
        rep(k,(int)G[j].size()) {
          Edge &e = G[j][k];
          if( maxi[e.dst] < min(maxi[j]+e.w,iHIT) ) {
            update = true;
            maxi[e.dst] = min(maxi[j]+e.w,iHIT);
            if( i == V*3 ) candidate.push_back(e.dst);
          }
        }
      }
    }
    
    //cout<<endl;
    //for(int i=0;i<(int)candidate.size();i++)cout<<candidate[i]<<endl;
    
    int maxValue = 0;
    rep(i,(int)candidate.size()) maxValue = max(maxValue,maxi[candidate[i]]);
    if( maxValue ) rep(i,(int)candidate.size()){
       
        if( maxValue == maxi[candidate[i]] ){
          
          gotoMaxi.push_back(candidate[i]);
        }
      }
    
    
  }
 
  /*
    
  */
 
 
  if( maxi[ep] == 0 ) puts("GAME OVER");
  else                cout << maxi[ep] << endl;
 
}
 
int main(){
  int CNT = 1;
  while( cin >> V >> E, V | E ){
    rep(i,V) G[i].clear();
    rep(i,E){
      int s,t,c;
      cin >> s >> t >> c;
      G[s].push_back((Edge){t,c});      
    }
    cin >> sp >> ep >> iHIT;
    cout << "Case " << CNT++ << ": ";
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 1276
final_rank: 4

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)

using namespace std;

struct Edge { int dst,w; };

const int MAX = 110;
int V,E,sp,ep,iHIT;
vector<Edge> G[MAX];
int maxi[MAX];


void compute(){
  bool update = true;
  rep(i,V) maxi[i] = 0;
  vector<int> gotoMaxi,candidate;
  gotoMaxi.push_back(sp);
  while( update ) {
    update = false;
    rep(i,(int)gotoMaxi.size()) maxi[gotoMaxi[i]] = iHIT;
    gotoMaxi.clear();
    candidate.clear();

    rep(i,V*3+1) {
      rep(j,V) if( j != ep && maxi[j] ) {
	rep(k,(int)G[j].size()) {
	  Edge &e = G[j][k];
	  if( maxi[e.dst] < min(maxi[j]+e.w,iHIT) ) {
	    update = true;
	    maxi[e.dst] = min(maxi[j]+e.w,iHIT);
	    if( i == V*3 ) candidate.push_back(e.dst);
	  }
	}
      }
    }
    
    int maxValue = 0;
    rep(i,(int)candidate.size()) maxValue = max(maxValue,maxi[candidate[i]]);
    if( maxValue ) rep(i,(int)candidate.size()) if( maxValue == maxi[candidate[i]] ) gotoMaxi.push_back(candidate[i]);

    
  }

  /*
  rep(i,V) {
    cout << i << "-th : " << maxi[i] << endl;
  } puts("");
  */


  if( maxi[ep] == 0 ) puts("GAME OVER");
  else                cout << maxi[ep] << endl;

}

int main(){
  int CNT = 1;
  while( cin >> V >> E, V | E ){
    rep(i,V) G[i].clear();
    rep(i,E){
      int s,t,c;
      cin >> s >> t >> c;
      G[s].push_back((Edge){t,c});
    }
    cin >> sp >> ep >> iHIT;
    cout << "Case " << CNT++ << ": ";
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 1276
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define MAX_N 105
#define INF (1e8)
struct edge{int from,to,cost;};
 
int n,m;
int si,ti,H;
 
vector<edge> E;
int d[MAX_N];
int prev[MAX_N];
int flg[MAX_N];
int G[MAX_N][MAX_N];
 
void init();
void input();
 
bool check(edge e){
  if(d[e.from]<=0)return false;
  int C=min(H,d[e.from]+e.cost);
   
  if(C<=d[e.to]||C<=0)return false;
  d[e.to]=C;
  prev[e.to]=e.from;
 
   
  int pos=e.from;
  map<int,bool> visited;
  vector<int> V;
  while(1){
    if(pos==-1)break;
    if(visited[pos])break;
    V.push_back(pos);
    visited[pos]=true;
    pos=prev[pos];
  }
  if(pos==-1||pos!=e.from)return true;
  reverse(V.begin(),V.end());
 
  int sum=0,size=V.size(),maxm=-INF;
  map<int,int> t;
  for(int i=0;i<size;i++){
    int p=V[i],q=V[(i+1)%size];
    sum=min(H,sum+G[p][q]);
    t[q]=sum;
    maxm=max(maxm,sum);
  }
  for(int i=0;i<size;i++){
    int p=V[i];
    if(t[p]==maxm)d[p]=H;    
  }
  return true;
}
 
void solve(){
  bool update=true;
  while(update){
    update=false;
    for(int i=0;i<(int)E.size();i++){
      if( check(E[i]) )update=true;
    }
  }
}
 
int main(){
  int Tc=1;
  while(1){
    cin>>n>>m;
    if(n==0&&m==0)break;
    init();
    input();
    solve();
    cout<<"Case "<<Tc++<<": ";
    if(d[ti]<=0)cout<<"GAME OVER"<<endl;
    else cout<<d[ti]<<endl;
  }
  return 0;
}
 
 
 
void init(){
  E.clear();
  for(int i=0;i<MAX_N;i++){
    d[i]=-INF;
    flg[i]=0;
    prev[i]=-1;
    for(int j=0;j<MAX_N;j++)G[i][j]=-INF;
  }
}
 
void input(){
  
  for(int i=0;i<m;i++){
    edge e;
    cin>>e.from>>e.to>>e.cost;
    G[e.from][e.to]=max(G[e.from][e.to],e.cost);
  }
  cin>>si>>ti>>H;
  d[si]=H;
  for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
      if(G[i][j]!=-INF&&i!=ti)
        E.push_back((edge){i,j,G[i][j]});
}
accuracy: 1
time_ms: 80
memory_kb: 1292
final_rank: 2

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define MAX_N 105
#define INF (1e8)
struct edge{int from,to,cost;};

int n,m;
int si,ti,H;

vector<edge> E;
int d[MAX_N];
int prev[MAX_N];
int flg[MAX_N];
int G[MAX_N][MAX_N];
bool er[MAX_N];

void init();
void input();


bool check(edge e){
  if(d[e.from]<=0)return false;
  int C=min(H,d[e.from]+e.cost);

  if(C==d[e.to]){
    prev[e.to]=e.from;
  }
  if(C<=d[e.to]||C<=0)return false;
  d[e.to]=C;
  prev[e.to]=e.from;

  if(er[e.to])d[e.to]=H;
  
  int pos=e.from;
  map<int,bool> visited;
  vector<int> V;
  while(1){
    if(pos==-1)break;
    if(visited[pos])break;
    V.push_back(pos);
    visited[pos]=true;
    pos=prev[pos];
  }
  if(pos==-1||pos!=e.from)return true;
  reverse(V.begin(),V.end());

  int sum=0,size=V.size(),maxm=-INF;
  map<int,int> t;
  for(int i=0;i<size;i++){
    int p=V[i],q=V[(i+1)%size];
    sum=min(H,sum+G[p][q]);
    t[q]=sum;
    maxm=max(maxm,sum);
  }
  for(int i=0;i<size;i++){
    int p=V[i];
    if(t[p]==maxm)d[p]=H;    
  }
  return true;
}

void solve(){
  bool update=true;
  while(update){
    update=false;
    for(int i=0;i<(int)E.size();i++){
      if( check(E[i]) )update=true;
    }
  }
}

int main(){
  int Tc=1;
  while(1){
    cin>>n>>m;
    if(n==0&&m==0)break;
    init();
    input();
    solve();

    cout<<"Case "<<Tc++<<": ";
    if(d[ti]<=0)cout<<"GAME OVER"<<endl;
    else cout<<d[ti]<<endl;
  }
  return 0;
}



void init(){
  E.clear();
  for(int i=0;i<MAX_N;i++){
    d[i]=-INF;
    er[i]=false;
    flg[i]=0;
    prev[i]=-1;
    for(int j=0;j<MAX_N;j++)G[i][j]=-INF;
  }
}

void input(){
 
  for(int i=0;i<m;i++){
    edge e;
    cin>>e.from>>e.to>>e.cost;
    if(e.from==e.to){
      er[e.to]=true;
      continue;
    }
    G[e.from][e.to]=max(G[e.from][e.to],e.cost);
  }
  cin>>si>>ti>>H;
  d[si]=H;
  er[ti]=false;
  for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
      if(G[i][j]!=-INF&&i!=ti)
        E.push_back((edge){i,j,G[i][j]});
}
accuracy: 1
time_ms: 80
memory_kb: 1292
final_rank: 2

code_snippet: #include<iostream>
#include<vector>
using namespace std;

typedef struct{
  int to,cost;
}Edge;

const int N = 100;
vector<Edge> edge[N];
int f[N];
int findMax(int n,int src,int maxhp){
  for(int i=0;i<n;i++){
    f[i] = 0;
  }
  for(int i=0;i<edge[src].size();i++){
    int next = edge[src][i].to;
    f[next] = max(f[next],maxhp+edge[src][i].cost);
    f[next] = min(f[next],maxhp-1);
  }
  //O(VE)
  for(int loop=0;loop<n-1;loop++){
    for(int i=0;i<n;i++){
      int now = i;
      if (f[now] == 0)continue;
      for(int j=0;j<edge[i].size();j++){
	int next = edge[now][j].to;
	f[next] = max(f[next],f[now]+edge[now][j].cost);
	f[next] = min(f[next],maxhp);
      }
    }
  }
  return f[src];
}

int cost[N];
int prevCost[N];
bool haveInfLoop[N];
int solve(int n,int src,int dst,int maxhp){
  edge[dst].clear();
  for(int i=0;i<n;i++){
    int tmp = findMax(n,i,maxhp);
    haveInfLoop[i] = tmp == maxhp;
  }


  for(int i=0;i<n;i++){
    cost[i] = 0;
    prevCost[i] = 0;
  }
  cost[src] = maxhp;
  prevCost[src] = maxhp;
  for(int loop=0;loop<n;loop++){
    for(int now=0;now<n;now++){
      if (cost[now] == 0)continue;
      for(int j=0;j<edge[now].size();j++){
	int next = edge[now][j].to;
	cost[next] = max(cost[next],cost[now]+edge[now][j].cost);
	cost[next] = min(cost[next],maxhp);
      }
    }

    for(int now=0;now<n;now++){
      if (cost[now] == 0)continue;
      for(int j=0;j<edge[now].size();j++){
	int next = edge[now][j].to;
	if (min(maxhp,cost[now] + edge[now][j].to)  != cost[next]){
	  //if (findMax(n,next,maxhp) == maxhp){
	  if (haveInfLoop[next]){
	    cost[next] = maxhp;
	  }
	}
      }
    }
  end:;
  }
  return cost[dst];
}

main(){
  int n,m;
  int tc = 1;
  while(cin>>n>>m && n){
    for(int i=0;i<n;i++){
      edge[i].clear();
    }
    for(int i=0;i<m;i++){
      int f,t,w;
      cin>>f>>t>>w;
      edge[f].push_back((Edge){t,w});
    }
    int s,t,hp;
    cin>>s>>t>>hp;
    int ans = solve(n,s,t,hp);
    cout <<"Case " << tc++ << ": ";
    if (ans == 0)cout <<"GAME OVER" << endl;
    else cout << ans << endl;
  }
  return false;
}
accuracy: 1
time_ms: 2420
memory_kb: 972
final_rank: 9

code_snippet: #include<iostream>
#include<vector>
using namespace std;

typedef struct{
  int to,cost;
}Edge;

const int N = 100;
vector<Edge> edge[N];
int f[N];
int findMax(int n,int src,int maxhp){
  for(int i=0;i<n;i++){
    f[i] = 0;
  }
  for(int i=0;i<edge[src].size();i++){
    int next = edge[src][i].to;
    f[next] = max(f[next],maxhp+edge[src][i].cost);
    f[next] = min(f[next],maxhp);
  }
  //O(VE)
  for(int loop=0;loop<n-1;loop++){
    for(int i=0;i<n;i++){
      int now = i;
      if (f[now] == 0)continue;
      for(int j=0;j<edge[i].size();j++){
	int next = edge[now][j].to;
	f[next] = max(f[next],f[now]+edge[now][j].cost);
	f[next] = min(f[next],maxhp);
      }
    }
  }
  return f[src];
}

int cost[N];
int prevCost[N];
bool haveInfLoop[N];
int solve(int n,int src,int dst,int maxhp){
  edge[dst].clear();
  for(int i=0;i<n;i++){
    int tmp = findMax(n,i,maxhp);
    haveInfLoop[i] = tmp == maxhp;
  }


  for(int i=0;i<n;i++){
    cost[i] = 0;
    prevCost[i] = 0;
  }
  cost[src] = maxhp;
  prevCost[src] = maxhp;
  for(int loop=0;loop<n;loop++){
    for(int now=0;now<n;now++){
      if (cost[now] == 0)continue;
      for(int j=0;j<edge[now].size();j++){
	int next = edge[now][j].to;
	cost[next] = max(cost[next],cost[now]+edge[now][j].cost);
	cost[next] = min(cost[next],maxhp);
      }
    }

    for(int now=0;now<n;now++){
      if (cost[now] == 0)continue;
      for(int j=0;j<edge[now].size();j++){
	int next = edge[now][j].to;
	if (min(maxhp,cost[now] + edge[now][j].to)  != cost[next]){
	  //if (findMax(n,next,maxhp) == maxhp){
	  if (haveInfLoop[next]){
	    cost[next] = maxhp;
	  }
	}
      }
    }
  end:;
  }
  return cost[dst];
}

main(){
  int n,m;
  int tc = 1;
  while(cin>>n>>m && n){
    for(int i=0;i<n;i++){
      edge[i].clear();
    }
    for(int i=0;i<m;i++){
      int f,t,w;
      cin>>f>>t>>w;
      edge[f].push_back((Edge){t,w});
    }
    int s,t,hp;
    cin>>s>>t>>hp;
    int ans = solve(n,s,t,hp);
    cout <<"Case " << tc++ << ": ";
    if (ans == 0)cout <<"GAME OVER" << endl;
    else cout << ans << endl;
  }
  return false;
}
accuracy: 1
time_ms: 2400
memory_kb: 972
final_rank: 8

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;

#define INF 0
#define SIZE 105

#define REP(i,n) for(int i=0; i<n; i++)

int c[SIZE];
bool loop[SIZE],tloop[SIZE];

bool relax_lim(int u, int v, int w, int l)
{
	int up=c[u]+w;
	if(up < l) up=l;
	if(c[v]>=up)
	{
		c[v]=up;
		return true;
	}
	
	return false;
}

class Edge
{
public:
	int s,d,c;
	Edge(){}
	Edge(int s,int d,int c)
	:s(s),d(d),c(c)
	{}
};

bool bellman_ford(vector<Edge>& g, int N, int s,int d,int MHP)
{
	REP(i,N) 
	{
		c[i]=(loop[i]?-MHP:c[i]);
	}
	
	memset(tloop,0,sizeof(tloop));
	
	c[s]=-MHP;
	
	REP(i,N-1) REP(j,g.size())
	{
		
		if(g[j].s==d) continue;
		if(g[j].d==d) continue;
		if(c[g[j].s]>=INF) continue;
		
		
		relax_lim(g[j].s,g[j].d,-g[j].c,-MHP);
	}
	bool ret=true;
	REP(j,g.size())
	{
		if(g[j].s==d) continue;
		if(g[j].d==d) continue;
		if(c[g[j].s]>=INF) continue;
		
		if(relax_lim(g[j].s,g[j].d,-g[j].c,-MHP)) 
		{
			if(-g[j].c < 0)
			{
				tloop[g[j].d]=1;
			}
		}
	}
	
	
	for(int i=0; i<N; i++)
	{
		if(tloop[i]!=loop[i])
		{
			ret=false;
			loop[i]=tloop[i];
		}
	}
	
	return ret;
}

int calc(vector<Edge>& g, int N, int s, int d, int MHP)
{
	REP(i,N) c[i]=(loop[i]?-MHP:INF);
	
	c[s]=-MHP;
	
	REP(i,N-1) REP(j,g.size())
	{
		if(g[j].s==d) continue;
		if(loop[g[j].d]) continue;
		if(c[g[j].s]>=INF) continue;
		relax_lim(g[j].s,g[j].d,-g[j].c,-MHP);
	}
	
	return -c[d];
}

int main()
{
	int N,M,C=1;
	while(cin >> N >> M, (N||M))
	{
		memset(c,0,sizeof(c));
		memset(loop,0,sizeof(loop));
		
		vector<Edge> g(M);
		for(int i=0; i<M; i++)
		{
			int s,d,c;
			cin >> s >> d >> c;
			g[i]=Edge(s,d,c);
		}
		
		int S,D,H;
		cin >> S >> D >> H;
		
		while(!bellman_ford(g,N,S,D,H));
		
		int ret=calc(g,N,S,D,H);
		
		cout << "Case " << C++ << ": ";
		if(ret<=INF) cout << "GAME OVER" << endl;
		else cout << ret << endl;
	}
}
accuracy: 1
time_ms: 210
memory_kb: 928
final_rank: 1