Problem:
問題 F : Social Monsters
問題文
不思議な生き物と人間が互いに助け合って生きている世界．
  この世界では自分で捕まえたモンスター同士を戦わせる大会が盛んに行われており，
  多くの少年少女達が世界一のトレーナーを目指している．
バトルでは自分が捕まえたモンスターからパーティを作り，パーティ同士の対戦となる．
  モンスターのペアには相性があり，相性が非常に悪い場合と普通の場合がある．
  相性が非常に悪い場合，そのペアのモンスターを同じパーティに入れることはできない．
  相性が普通の場合には，
友情度
という数値で相性の良さが表現される．
  バトルでは，パーティ全体の友情度の和が勝負の鍵となる．
いま
N
匹のモンスターから
K
匹のモンスターからなるパーティを作りたい．
M
個のモンスターのペア
(a_i,   b_i)
に対して相性が分かっており，整数
c_i
で表されている．
c_i = 0
のとき，
a_i
番目のモンスターと
b_i
番目のモンスターは相性が非常に悪いことを意味する．
c_i  ≠  0
のとき，
a_i
番目のモンスターと
b_i
番目のモンスターは相性が普通であり，その友情度は
c_i
であることを意味する．
  与えられた
M
個のペア以外は，相性が普通であり，それらの友情度はすべて
0
である．
パーティの友情度の和を最大にする選び方を考えてみよう．
入力形式
入力は以下の形式で与えられる
N
M
K
a_0
b_0
c_0
...
a_{M-1}
b_{M-1}
c_{M-1}
出力形式
K
匹のモンスターからなるパーティを作ることができない場合は1行に "Impossible" を出力せよ．
パーティを作ることができるとき，友情度の和の最大値を出力せよ．
制約
1 ≤ K ≤ N ≤ 2000
0 ≤ M ≤ N
1   ≤   a_i   ≠   b_i   ≤ N
|c_i|   ≤ 10000
各モンスターは
a_0, a_1, …, a_{M-1}, b_0, b_1, …, b_{M-1}
の中に高々2回しか現れない．
i   ≠   j   ⇒  
\{a_i, b_i\}   ≠   \{a_j,   b_j\}
入出力例
入力例 1
6 5 4
2 1 1
2 5 2
5 1 1
4 3 2
3 6 -1
出力例 1
4
入力例 2
3 1 3
1 2 -10
出力例 2
-10
入力例 2
6 3 5
1 2 0
2 3 10
3 4 0
出力例 2
Impossible

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

void chmax(ll &a, ll b) { a = max(a, b); }
vector<ll> solve(vector<ll> path) {
    int n = path.size() + 1;
    vector dp(n + 1, vector(2, -INF));
    dp[0][0] = dp[1][1] = 0;
    foa(e, path) {
        vector nx(n + 1, vector(2, -INF));
        rep(i, n + 1) {
            if(e == 0) {
                if(i < n) chmax(nx[i + 1][1], dp[i][0]);
                chmax(nx[i][0], dp[i][1]);
                chmax(nx[i][0], dp[i][0]);
            } else {
                if(i < n) chmax(nx[i + 1][1], dp[i][1] + e);
                if(i < n) chmax(nx[i + 1][1], dp[i][0]);
                chmax(nx[i][0], dp[i][1]);
                chmax(nx[i][0], dp[i][0]);
            }
        }
        swap(nx, dp);
    }
    vector<ll> ret(n + 1);
    rep(i, n + 1) ret[i] = max(dp[i][0], dp[i][1]);
    while(!ret.empty() and ret.back() < -INF/2) ret.pop_back();
    return ret;
}
vector<ll> solveo(vector<ll> path) {
    int n = path.size();
    vector dp(n + 1, vector(2, vector(2, -INF)));
    dp[0][0][0] = dp[1][1][1] = 0; // cnt, prev, anc
    path.back() += (1LL << 30);
    foa(e, path) {
        vector nx(n + 1, vector(2, vector(2, -INF)));
        if(e >= (1LL << 29)) {
            e -= (1LL << 30);
            rep(i, n + 1) {
                if(e == 0) {
                    dp[i][1][1] = -INF;
                } else {
                    dp[i][1][1] += e;
                }
            }
            break;
        }
        rep(i, n + 1) {
            {
                rep(j, 2) {
                    if(e == 0) {
                        if(i < n) chmax(nx[i + 1][1][j], dp[i][0][j]);
                        chmax(nx[i][0][j], dp[i][1][j]);
                        chmax(nx[i][0][j], dp[i][0][j]);
                    } else {
                        if(i < n) chmax(nx[i + 1][1][j], dp[i][1][j] + e);
                        if(i < n) chmax(nx[i + 1][1][j], dp[i][0][j]);
                        chmax(nx[i][0][j], dp[i][1][j]);
                        chmax(nx[i][0][j], dp[i][0][j]);
                    }
                }                    
            }
        }
        swap(nx, dp);
    }
    // rep(i, n + 1) {
    //     rep(j, 2) rep(k, 2) cout << dp[i][j][k] << " ";
    //     cout << endl;
    // }
    vector<ll> ret(n + 1, -INF);
    rep(i, n + 1) rep(j, 2) rep(k, 2) chmax(ret[i], dp[i][j][k]);
    while(!ret.empty() and ret.back() < -INF/2) ret.pop_back();
    return ret;
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll n, m, k; cin >> n >> m >> k;
    vector<vector<pair<ll, ll>>> v(n);
    rep(i, m) {
        ll a, b, c; cin >> a >> b >> c;
        a --; b --;
        v[a].push_back({b, c});
        v[b].push_back({a, c});
    }
    vector<vector<ll>> rets;
    vector<int> seen(n, 0);
    vector<ll> path;
    auto dfs = [&](auto dfs, int now, int p) -> void {
        seen[now] = 1;
        for(auto [x, y] : v[now]) {
            if(seen[x]) continue;
            path.pb(y);
            dfs(dfs, x, now);
        }
    };
    rep(i, n) {
        if(!seen[i] and (int)v[i].size() <= 1) {
            if(v[i].empty()) {
                // cout << "a" << endl;
                rets.push_back(vector<ll> (2, 0));
                seen[i] = 1;
            } else {
                path.clear();
                dfs(dfs, i, -1);
                // foa(e, path) cout << e << " ";
                // cout << endl;
                rets.pb(solve(path));
            }
        }
    }
    rep(i, n) {
        if(!seen[i]) {
            seen[i] = 1;
            path.clear();
            path.pb(v[i][0].second);
            path.pb(v[i][1].second);
            dfs(dfs, v[i][1].first, i);
            // foa(e, path) cout << e << " " ;
            // cout << endl;
            rets.pb(solveo(path));
        }
    }

    vector<ll> dp(1, 0);
    foa(vec, rets) {
        // foa(e, vec) cout << e << " ";
        // cout << endl;
        int sz1 = dp.size();
        int sz2 = vec.size();
        vector<ll> nx(sz1 + sz2 - 1, -INF);
        rep(i, sz1) rep(j, sz2) {
            chmax(nx[i + j], dp[i] + vec[j]);
        }
        dp = move(nx);
    }
    if((int)dp.size() < k + 1) {
        cout << "Impossible" << endl;
    } else {
        cout << dp[k] << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 350
memory_kb: 4032
final_rank: 6

code_snippet: // AOJ #2605
// Social Monsters 2025.2.7
 
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
 
const ll NEG_INF = - (1LL << 60);
 
vector<ll> solvePathDP(int L, const vector<int>& weights) {
    vector<vector<ll>> dp(L+1, vector<ll>(2, NEG_INF));
    dp[0][0] = 0;
    dp[1][1] = 0;
 
    for (int i = 0; i < L-1; i++){
        vector<vector<ll>> newdp(L+1, vector<ll>(2, NEG_INF));
        int w = weights[i];
        for (int r = 0; r <= L; r++){
            for (int s = 0; s < 2; s++){
                if(dp[r][s] == NEG_INF) continue;
                newdp[r][0] = max(newdp[r][0], dp[r][s]);
                if(r+1 <= L){
                    if(s == 1){
                        if(w != 0)
                            newdp[r+1][1] = max(newdp[r+1][1], dp[r][s] + w);
                    } else {
                        newdp[r+1][1] = max(newdp[r+1][1], dp[r][s]);
                    }
                }
            }
        }
        dp = move(newdp);
    }
    vector<ll> res(L+1, NEG_INF);
    for (int r = 0; r <= L; r++){
        res[r] = max(dp[r][0], dp[r][1]);
    }
    return res;
}
 
vector<ll> solveCycleDP(int L, const vector<int>& weights, int w_last) {
    vector<vector<ll>> dp1(L+1, vector<ll>(2, NEG_INF));
    dp1[0][0] = 0;
    for (int i = 0; i < L-1; i++){
        vector<vector<ll>> newdp(L+1, vector<ll>(2, NEG_INF));
        int w = weights[i];
        for (int r = 0; r <= L; r++){
            for (int s = 0; s < 2; s++){
                if(dp1[r][s] == NEG_INF) continue;
                newdp[r][0] = max(newdp[r][0], dp1[r][s]);
                if(r+1 <= L){
                    if(s==1){
                        if(w != 0)
                            newdp[r+1][1] = max(newdp[r+1][1], dp1[r][s] + w);
                    } else {
                        newdp[r+1][1] = max(newdp[r+1][1], dp1[r][s]);
                    }
                }
            }
        }
        dp1 = move(newdp);
    }
    vector<ll> res1(L+1, NEG_INF);
    for (int r = 0; r <= L; r++){
        res1[r] = max(dp1[r][0], dp1[r][1]);
    }
 
    vector<vector<ll>> dp2(L+1, vector<ll>(2, NEG_INF));
    dp2[1][1] = 0;
    for (int i = 0; i < L-1; i++){
        vector<vector<ll>> newdp(L+1, vector<ll>(2, NEG_INF));
        int w = weights[i];
        for (int r = 0; r <= L; r++){
            for (int s = 0; s < 2; s++){
                if(dp2[r][s] == NEG_INF) continue;
                newdp[r][0] = max(newdp[r][0], dp2[r][s]);
                if(r+1 <= L){
                    if(s==1){
                        if(w != 0)
                            newdp[r+1][1] = max(newdp[r+1][1], dp2[r][s] + w);
                    } else {
                        newdp[r+1][1] = max(newdp[r+1][1], dp2[r][s]);
                    }
                }
            }
        }
        dp2 = move(newdp);
    }
    vector<ll> res2(L+1, NEG_INF);
    for (int r = 0; r <= L; r++){
        res2[r] = max(res2[r], dp2[r][0]);
        if(dp2[r][1] != NEG_INF){
            if(w_last != 0)
                res2[r] = max(res2[r], dp2[r][1] + w_last);
        }
    }
    vector<ll> res(L+1, NEG_INF);
    for (int r = 0; r <= L; r++){
        res[r] = max(res1[r], res2[r]);
    }
    return res;
}
 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    int N, M, K;
    cin >> N >> M >> K;
    vector<vector<pair<int,int>>> graph(N+1);
    for (int i = 0; i < M; i++){
        int a, b, c;
        cin >> a >> b >> c;
        graph[a].push_back({b, c});
        graph[b].push_back({a, c});
    }
 
    vector<bool> visited(N+1, false);
    vector<vector<ll>> compDPs;
 
    for (int v = 1; v <= N; v++){
        if(visited[v]) continue;
        vector<int> comp;
        queue<int> q;
        q.push(v);
        visited[v] = true;
        while(!q.empty()){
            int cur = q.front(); q.pop();
            comp.push_back(cur);
            for(auto &edge : graph[cur]){
                int nb = edge.first;
                if(!visited[nb]){
                    visited[nb] = true;
                    q.push(nb);
                }
            }
        }
 
        if(comp.size() == 1){
            vector<ll> f(2, NEG_INF);
            f[0] = 0; f[1] = 0;
            compDPs.push_back(f);
            continue;
        }
 
        bool isPath = false;
        for (int u : comp){
            if ((int)graph[u].size() == 1){
                isPath = true;
                break;
            }
        }
 
        vector<int> order;
        vector<int> weights;
 
        if(isPath){
            int start = -1;
            for (int u : comp){
                if((int)graph[u].size() == 1){
                    start = u;
                    break;
                }
            }
            int prev = -1, cur = start;
            while (true) {
                order.push_back(cur);
                int nxt = -1, wVal = 0;
                for(auto &pr : graph[cur]){
                    if(pr.first == prev) continue;
                    nxt = pr.first;
                    wVal = pr.second;
                    break;
                }
                if(nxt == -1) break;
                weights.push_back(wVal);
                prev = cur;
                cur = nxt;
            }
            int Lchain = order.size();
            vector<ll> f = solvePathDP(Lchain, weights);
            compDPs.push_back(f);
 
        } else {
            int start = comp[0];
            int prev = -1, cur = start;
            while (true) {
                order.push_back(cur);
                int nxt = -1, wVal = 0;
                for(auto &pr : graph[cur]){
                    if(pr.first == prev) continue;
                    nxt = pr.first;
                    wVal = pr.second;
                    break;
                }
                if(nxt == start) break;
                weights.push_back(wVal);
                prev = cur;
                cur = nxt;
            }
            int Lcycle = order.size();
            int w_last = 0;
            int lastV = order.back();
            for(auto &pr : graph[lastV]){
                if(pr.first == start){
                    w_last = pr.second;
                    break;
                }
            }
            vector<ll> f = solveCycleDP(Lcycle, weights, w_last);
            compDPs.push_back(f);
        }
    }
 
    vector<ll> globalDP(K+1, NEG_INF);
    globalDP[0] = 0;
    for(auto &f : compDPs){
        int compSize = f.size() - 1;
        vector<ll> newDP(K+1, NEG_INF);
        for (int x = 0; x <= K; x++){
            if(globalDP[x] == NEG_INF) continue;
            for (int r = 0; r <= compSize; r++){
                if(x + r <= K && f[r] != NEG_INF){
                    newDP[x + r] = max(newDP[x + r], globalDP[x] + f[r]);
                }
            }
        }
        globalDP = move(newDP);
    }
     if(globalDP[K] == NEG_INF) cout << "Impossible" << endl;
    else                       cout << globalDP[K]  << endl;
    return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 3776
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
using pii = pair<int, int>;
#define rep(i, x) for(int i = 0; i < (x); i++)
#define rng(i, l, r) for(int i = (l); i < (r); i++)
#define all(v) (v).begin(), (v).end()
#define sz(v) (int)(v).size()
const int inf = 1 << 29;

void chmax(int &x, int y) {
	x = x < y ? y : x;
}

int main() {
	int n, m, k;
	cin >> n >> m >> k;
	vector<vi> g(n);
	vi in(n);
	vector<vi> dist(n, vi(n, -inf));
	rep(i, m) {
		int u, v, c;
		cin >> u >> v >> c, --u, --v;
		g[u].emplace_back(v);
		g[v].emplace_back(u);
		dist[u][v] = dist[v][u] = c;
		in[u]++, in[v]++;
	}
	vector dp_all(n + 1, -inf);
	int zero = count(all(in), 0);
	rep(i, zero + 1) dp_all[i] = 0;
	int sum = zero;
	vector<int> vis(n);
	rep(i, n) {
		if(in[i] == 1 and !vis[i]) {
			vi path;
			auto get_path = [&](auto self, int v) -> void {
				if(vis[v]) return;
				vis[v] = 1;
				path.push_back(v);
				for(auto to : g[v]) self(self, to);
			};
			get_path(get_path, i);
			int len = sz(path);
			vector dp(len + 1, vector(2, -inf));
			dp[0][0] = 0;
			dp[1][1] = 0;
			rng(i, 1, len) {
				vector ndp(len + 1, vector(2, -inf));
				rep(j, i + 1) {
					rep(f, 2) {
						rep(nx, 2) {
							int bef = path[i - 1];
							int now = path[i];
							int val = dp[j][f];
							if(f and nx) {
								if(dist[bef][now] == 0)
									val = -inf;
								else
									val += dist[bef][now];
							}
							chmax(ndp[j + nx][nx], val);
						}
					}
				}
				dp = ndp;
			}
			auto ndp = dp_all;
			for(int i = sum; i >= 0; --i) {
				rep(j, len + 1) {
					chmax(ndp[i + j], dp_all[i] + max(dp[j][0], dp[j][1]));
				}
			}
			dp_all = move(ndp);
			sum += sz(path);
		}
	}
	rep(i, n) {
		if(in[i] == 2 and !vis[i]) {
			vi path;
			auto get_path = [&](auto self, int v) -> void {
				if(vis[v]) return;
				vis[v] = 1;
				path.push_back(v);
				for(auto to : g[v]) self(self, to);
			};
			get_path(get_path, i);
			int len = sz(path);
			vector dp(len + 1, vector(2, vector(2, -inf)));
			dp[0][0][0] = 0;
			dp[1][1][1] = 0;
			rng(i, 1, len) {
				vector ndp(len + 1, vector(2, vector(2, -inf)));
				rep(j, i + 1) {
					rep(f, 2) {
						rep(nx, 2) {
							rep(fi, 2) {
								int bef = path[i - 1];
								int now = path[i];
								int val = dp[j][f][fi];
								if(f and nx) {
									if(dist[bef][now] == 0)
										val = -inf;
									else
										val += dist[bef][now];
								}
								chmax(ndp[j + nx][nx][fi], val);
							}
						}
					}
				}
				dp = move(ndp);
			}
			vi items(len + 1, -inf);
			rep(i, len + 1) {
				rep(t, 2) {
					rep(fi, 2) {
						if(t + fi == 2) {
							if(dist[path[0]][path.back()]) {
								dp[i][t][fi] += dist[path[0]][path.back()];
							} else {
								dp[i][t][fi] = -inf;
							}
						}
						chmax(items[i], dp[i][t][fi]);
					}
				}
			}
			auto ndp = dp_all;
			for(int i = sum; i >= 0; --i) {
				rep(j, len + 1) {
					if(dp_all[i] != -inf and items[j] != -inf)
						chmax(ndp[i + j], dp_all[i] + items[j]);
				}
			}
			dp_all = move(ndp);
			sum += sz(path);
		}
	}
	if(dp_all[k] <= -inf / 2)
		cout << "Impossible\n";
	else
		cout << dp_all[k] << endl;
}
accuracy: 1
time_ms: 360
memory_kb: 19740
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
using pii = pair<int, int>;
#define rep(i, x) for(int i = 0; i < (x); i++)
#define rng(i, l, r) for(int i = (l); i < (r); i++)
#define all(v) (v).begin(), (v).end()
#define sz(v) (int)(v).size()
const int inf = 1 << 29;

void chmax(int &x, int y) {
	x = x < y ? y : x;
}

int main() {
	int n, m, k;
	cin >> n >> m >> k;
	vector<vi> g(n);
	vi in(n);
	vector<vi> dist(n, vi(n, -inf));
	rep(i, m) {
		int u, v, c;
		cin >> u >> v >> c, --u, --v;
		g[u].emplace_back(v);
		g[v].emplace_back(u);
		dist[u][v] = dist[v][u] = c;
		in[u]++, in[v]++;
	}
	vector dp_all(n + 1, -inf);
	int zero = count(all(in), 0);
	rep(i, zero + 1) dp_all[i] = 0;
	int sum = zero;
	vector<int> vis(n);
	rep(i, n) {
		if(in[i] == 1 and !vis[i]) {
			vi path;
			auto get_path = [&](auto self, int v) -> void {
				if(vis[v]) return;
				vis[v] = 1;
				path.push_back(v);
				for(auto to : g[v]) self(self, to);
			};
			get_path(get_path, i);
			int len = sz(path);
			vector dp(len + 1, vector(2, -inf));
			dp[0][0] = 0;
			dp[1][1] = 0;
			rng(i, 1, len) {
				vector ndp(len + 1, vector(2, -inf));
				rep(j, i + 1) {
					rep(f, 2) {
						rep(nx, 2) {
							int bef = path[i - 1];
							int now = path[i];
							int val = dp[j][f];
							if(f and nx) {
								if(dist[bef][now] == 0)
									val = -inf;
								else
									val += dist[bef][now];
							}
							chmax(ndp[j + nx][nx], val);
						}
					}
				}
				dp = ndp;
			}
			auto ndp = dp_all;
			for(int i = sum; i >= 0; --i) {
				rep(j, len + 1) {
					chmax(ndp[i + j], dp_all[i] + max(dp[j][0], dp[j][1]));
				}
			}
			dp_all = move(ndp);
			sum += sz(path);
		}
	}
	rep(i, n) {
		if(in[i] == 2 and !vis[i]) {
			vi path;
			auto get_path = [&](auto self, int v) -> void {
				if(vis[v]) return;
				vis[v] = 1;
				path.push_back(v);
				for(auto to : g[v]) self(self, to);
			};
			get_path(get_path, i);
			int len = sz(path);
			vector dp(len + 1, vector(2, vector(2, -inf)));
			dp[0][0][0] = 0;
			dp[1][1][1] = 0;
			rng(i, 1, len) {
				vector ndp(len + 1, vector(2, vector(2, -inf)));
				rep(j, i + 1) {
					rep(f, 2) {
						rep(nx, 2) {
							rep(fi, 2) {
								int bef = path[i - 1];
								int now = path[i];
								int val = dp[j][f][fi];
								if(f and nx) {
									if(dist[bef][now] == 0)
										val = -inf;
									else
										val += dist[bef][now];
								}
								chmax(ndp[j + nx][nx][fi], val);
							}
						}
					}
				}
				dp = move(ndp);
			}
			vi items(len + 1, -inf);
			rep(i, len + 1) {
				rep(t, 2) {
					rep(fi, 2) {
						if(t + fi == 2) {
							if(dist[path[0]][path.back()]) {
								dp[i][t][fi] += dist[path[0]][path.back()];
							} else {
								dp[i][t][fi] = -inf;
							}
						}
						chmax(items[i], dp[i][t][fi]);
					}
				}
			}
			auto ndp = dp_all;
			for(int i = sum; i >= 0; --i) {
				rep(j, len + 1) {
					if(dp_all[i] != -inf and items[j] != -inf)
						chmax(ndp[i + j], dp_all[i] + items[j]);
				}
			}
			dp_all = move(ndp);
			sum += sz(path);
		}
	}
	if(dp_all[k] <= -inf / 2)
		cout << "Impossible\n";
	else
		cout << dp_all[k] << endl;
}
accuracy: 1
time_ms: 360
memory_kb: 19824
final_rank: 9

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

using namespace std;

#define rep(i, a, b) for (ll i = (ll)(a); i < (ll)(b); i++)
#define rrep(i, a, b) for (ll i = (ll)(b)-1; i >= (ll)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int main() {
    int N, M, K;
    cin >> N >> M >> K;
    vector<vector<pair<int,int>>> G(N);
    rep(i,0,M) {
        int A, B, C;
        cin >> A >> B >> C;
        A--, B--;
        G[A].push_back({B,C});
        G[B].push_back({A,C});
    }
    vector<bool> used(N,false);
    vector<int> ANS(N+1,-inf);

    //Isolate Pattern
    int Isolate = 0;
    rep(i,0,N) {
        if (G[i].empty()) {
            used[i] = true;
            Isolate++;
        }
    }
    rep(i,0,Isolate+1) ANS[i] = 0;

    //Line Pattern
    rep(i,0,N) {
        if (G[i].size() == 1 && !used[i]) {
            vector<int> Line;
            vector<int> Connect;
            queue<int> Q;
            Q.push(i);
            while(!Q.empty()) {
                int P = Q.front();
                Q.pop();
                Line.push_back(P);
                used[P] = true;
                for(auto E : G[P]) {
                    auto [NP, D] = E;
                    if (!used[NP]) {
                        Q.push(NP);
                        Connect.push_back(D);
                    }
                }
            }
            int L = Line.size();
            vector<vector<int>> DP(L+1,vector<int>(2,-inf));
            DP[0][0] = DP[1][1] = 0;
            rep(_,0,L-1) {
                int D = Connect[_];
                vector<vector<int>> NewDP(L+1,vector<int>(2,-inf));
                if (D == 0) {
                    rep(j,0,L+1) {
                        rep(k,0,2) {
                            if (DP[j][k] != -inf) {
                                chmax(NewDP[j][0],DP[j][k]);
                                if (k != 1) chmax(NewDP[j+1][1],DP[j][k]);
                            }
                        }
                    }
                }
                else {
                    rep(j,0,L+1) {
                        rep(k,0,2) {
                            if (DP[j][k] != -inf) {
                                chmax(NewDP[j][0],DP[j][k]);
                                if (k == 0) chmax(NewDP[j+1][1],DP[j][k]);
                                else chmax(NewDP[j+1][1],DP[j][k]+D);
                            }
                        }
                    }
                }
                swap(DP,NewDP);
            }
            vector<int> NewANS(N+1,-inf);
            rep(j,0,L+1) {
                int MAX = max(DP[j][0],DP[j][1]);
                if (MAX == -inf) continue;
                rep(k,0,N-j+1) {
                    if (ANS[k] != -inf) chmax(NewANS[k+j],ANS[k]+MAX);
                }
            }
            swap(ANS,NewANS);
        }
    }

    //Loop Pattern
    rep(i,0,N) {
        if (used[i]) continue;
        vector<int> Loop;
        vector<int> Connect;
        Loop.push_back(i);
        used[i] = true;
        queue<int> Q;
        Q.push(G[i][0].first);
        Connect.push_back(G[i][0].second);
        int Another = G[i][1].second;
        while(!Q.empty()) {
            int P = Q.front();
            Q.pop();
            Loop.push_back(P);
            used[P] = true;
            for(auto E : G[P]) {
                auto [NP, D] = E;
                if (!used[NP]) {
                    Q.push(NP);
                    Connect.push_back(D);
                }
            }
        }
        int L = Loop.size();
        vector<vector<vector<int>>> DP(L+1, vector<vector<int>>(2,vector<int>(2,-inf)));
        DP[0][0][0] = DP[1][1][1] = 0;
        rep(_,0,L-1) {
            int D = Connect[_];
            vector<vector<vector<int>>> NewDP(L+1, vector<vector<int>>(2,vector<int>(2,-inf)));
            if (D == 0) {
                rep(j,0,L+1) {
                    rep(k,0,2) {
                        rep(l,0,2) {
                            if (DP[j][k][l] == -inf) continue;
                            chmax(NewDP[j][0][l],DP[j][k][l]);
                            if (k == 0) chmax(NewDP[j+1][1][l],DP[j][k][l]);
                        }
                    }
                }
            }
            else {
                rep(j,0,L+1) {
                    rep(k,0,2) {
                        rep(l,0,2) {
                            if (DP[j][k][l] == -inf) continue;
                            chmax(NewDP[j][0][l],DP[j][k][l]);
                            if (k == 0) chmax(NewDP[j+1][1][l],DP[j][k][l]);
                            else chmax(NewDP[j+1][1][l],DP[j][k][l]+D);
                        }
                    }
                }
            }
            swap(DP,NewDP);
        }
        vector<int> NewANS(N+1,-inf);
        rep(j,0,L+1) {
            int MAX = max(max(DP[j][0][0],DP[j][1][0]),DP[j][0][1]);
            if (Another != 0 && DP[j][1][1] != -inf) chmax(MAX,DP[j][1][1]+Another);
            if (MAX == -inf) continue;
            rep(k,0,N-j+1) {
                if (ANS[k] != -inf) chmax(NewANS[k+j],ANS[k]+MAX);
            }
        }
        swap(ANS,NewANS);
    }
    if (ANS[K] == -inf) cout << "Impossible" << endl;
    else cout << ANS[K] << endl;
}
accuracy: 1
time_ms: 350
memory_kb: 3824
final_rank: 5

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

const long long INVALID{-(long long)1e12};

std::mt19937 mt{std::random_device{}()};

long long brute(const std::vector<std::vector<std::pair<int, long long>>>& g, int K) {
    std::vector table(g.size(), std::vector<long long>(g.size()));
    for (int v{} ; v < (int)g.size() ; v++) {
        for (auto [x, c] : g[v]) table[v][x] = c;
    }
    long long res{INVALID};
    for (int bit{} ; bit < (1 << (int)g.size()) ; bit++) {
        if (__builtin_popcount(bit) != K) continue;
        std::vector<int> use;
        for (int i{} ; i < (int)g.size() ; i++) if (bit & (1 << i)) {
            use.push_back(i);
        }
        assert(use.size() == (unsigned)K);
        long long val{};
        bool can{true};
        for (int i{} ; i < K ; i++) {
            for (int j{i + 1} ; j < K ; j++) {
                if (table[use[i]][use[j]] == INVALID) can = false;
                val += table[use[i]][use[j]];
            }
        }
        if (can) {
            res = std::max(val, res);
        }
    }
    return res;
}

void solve() {
    int N, M, K;
    std::cin >> N >> M >> K;
    //N = mt() % 15 + 1;
    //K = mt() % N + 1;
    std::vector<std::vector<std::pair<int, long long>>> g(N);
    //do {
    //    bool cyc{mt() % 2};
    //    int bit{mt() % (1 << N)};
    //    std::vector<int> comp;
    //    for (int i{} ; i < N ; i++) {
    //        if (bit & (1 << i)) comp.push_back(i);
    //    }
    //    if (comp.size() <= 1u) break;
    //    for (int i{} ; i + 1 < (int)comp.size() ; i++) {
    //        int u{comp[i]}, v{comp[i + 1]};
    //        long long cost{mt() % 11};
    //        cost -= 5;
    //        if (cost == 0) cost = INVALID;
    //        g[u].emplace_back(v, cost);
    //        g[v].emplace_back(u, cost);
    //    }
    //    if (cyc) {
    //        int u{comp.back()}, v{comp.front()};
    //        long long cost{mt() % 11};
    //        cost -= 5;
    //        if (cost == 0) cost = INVALID;
    //        g[u].emplace_back(v, cost);
    //        g[v].emplace_back(u, cost);
    //    }
    //} while (false);

    // 0.. no edge
    // INVALID .. dame!
    // other .. friend
    for (int i{} ; i < M ; i++) {
        int a, b;
        long long c;
        std::cin >> a >> b >> c;
        a--; b--;
        if (c == 0) c = INVALID;
        g[a].emplace_back(b, c);
        g[b].emplace_back(a, c);
    }

    std::vector<bool> vis(N);
    auto dfs{[&](auto dfs, int v, std::vector<int>& comp) -> void {
        vis[v] = true;
        comp.push_back(v);
        for (auto [x, _] : g[v]) {
            if (vis[x]) continue;
            dfs(dfs, x, comp);
        }
    }};
    auto isCyc{[&](const std::vector<int>& comp) -> bool {
        bool res{true};
        for (auto v : comp) res &= (g[v].size() == 2u);
        return res;
    }};
    auto getOrder{[&](const std::vector<int>& comp) -> std::vector<int> {
        int cur{-1};
        for (auto v : comp) {
            if (g[v].size() == 1u) {
                cur = v;
            }
        }
        assert(cur != -1);
        std::vector<bool> used(N);
        std::vector<int> res;
        while (true) {
            used[cur] = true;
            int next{-1};
            res.push_back(cur);
            for (auto [x, _] : g[cur]) {
                if (used[x]) continue;
                assert(next == -1);
                next = x;
            }
            if (next == -1) break;
            cur = next;
        }
        return res;
    }};
    auto getAdjCost{[&](const std::vector<int>& comp) -> std::vector<long long> {
        std::vector<long long> res;
        for (int i{} ; i < (int)comp.size() ; i++) {
            int u{comp[i]}, v{comp[(i + 1) % comp.size()]};
            long long cost{};
            for (auto [x, c] : g[u]) {
                if (x == v) cost = c;
            }
            if (cost == 0) {
                assert(i < (int)comp.size());
            }
            res.push_back(cost);
        }
        return res;
    }};
    std::vector<long long> dp(1);
    for (int v{} ; v < N ; v++) {
        if (vis[v]) continue;
        std::vector<int> comp;
        dfs(dfs, v, comp);
        assert(comp.size());
        if (comp.size() == 1u) {
            std::vector<long long> next(dp.size() + 1, INVALID);
            for (int i{} ; i < (int)dp.size() ; i++) {
                if (dp[i] == INVALID) continue;
                next[i] = std::max(next[i], dp[i]);
                next[i + 1] = std::max(next[i + 1], dp[i]);
            }
            dp = std::move(next);
            continue;
        }
        bool cyc{isCyc(comp)};
        if (!cyc) {
            comp = getOrder(comp);
        }

        //for (auto x : comp) std::cout << x + 1 << ' ';
        //std::cout << std::endl;

        std::vector<long long> cost{getAdjCost(comp)};

        //for (auto c : cost) std::cout << c << ' ';
        //std::cout << std::endl;
        
        std::vector<long long> max(comp.size() + 1, INVALID);
        for (int bit{} ; bit < 2 ; bit++) {
            std::vector dp2(2, std::vector<long long>(2, INVALID));
            dp2[bit][bit] = 0;
            for (int i{} ; i + 1 < (int)cost.size() ; i++) {
                std::vector next2(2, std::vector<long long>(dp2[0].size() + 1, INVALID));
                for (int j{} ; j < 2 ; j++) {
                    for (int k{} ; k < (int)dp2[j].size() ; k++) {
                        if (dp2[j][k] == INVALID) continue;
                        next2[0][k] = std::max(next2[0][k], dp2[j][k]);
                        if (j == 1 and cost[i] == INVALID) continue;
                        long long val{(j == 1 ? cost[i] : 0LL)};
                        next2[1][k + 1] = std::max(next2[1][k + 1], dp2[j][k] + val);
                    }
                }
                dp2 = std::move(next2);
            }
            assert(dp2[0].size() == comp.size() + 1);
            for (int i{} ; i <= (int)comp.size() ; i++) {
                if (dp2[0][i] != INVALID) {
                    max[i] = std::max(max[i], dp2[0][i]);     
                }
                if (dp2[1][i] == INVALID) continue;
                if (comp.size() == 2u) {
                    max[i] = std::max(max[i], dp2[1][i]);
                }
                else {
                    if (bit == 1 and cost.back() == INVALID) continue;
                    max[i] = std::max(max[i], dp2[1][i] + (bit == 1 ? cost.back() : 0LL));
                }
            }
        }
        //std::cout << "max" << std::endl;
        //for (int i{} ; i <= (int)comp.size() ; i++) {
        //    std::cout << max[i] << ' ';
        //}
        //std::cout << std::endl;
        std::vector<long long> next(dp.size() + comp.size(), INVALID);
        for (int i{} ; i < (int)dp.size() ; i++) {
            if (dp[i] == INVALID) continue;
            for (int j{} ; j <= (int)comp.size() ; j++) {
                if (max[j] == INVALID) continue;
                next[i + j] = std::max(next[i + j], dp[i] + max[j]);
            }
        }
        dp = std::move(next);
    }
    //std::cout << dp[K] << ' ' << brute(g, K) << std::endl;
    //if (dp[K] != brute(g, K)) {
    //    std::cout << N << ' ' << K << std::endl;
    //    for (int v{} ; v < N ; v++) {
    //        std::cout << v + 1 << " : ";
    //        for (auto [x, c] : g[v]) std::cout << '(' << x + 1 << ',' << c <<')' << ' ';
    //        std::cout << std::endl;
    //    }
    //    std::cout << "brute value is " << brute(g, K) << std::endl;
    //    std::cout << "your answer is " << dp[K] << std::endl;
    //    exit(0);
    //}
    if (dp[K] == INVALID) {
        std::cout << "Impossible" << '\n';
    }
    else {
        std::cout << dp[K] << '\n';
    }
}

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    solve();

    //while (true) {
    //    std::cout << "test " << std::endl;
    //    solve();
    //}
}
accuracy: 1
time_ms: 10
memory_kb: 3996
final_rank: 1

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

const long long INF = 1e18;
std::vector<std::pair<int, long long>> path(const std::vector<long long>& a) {
    // n: 頂点数
    int n = a.size() + 1;
    std::vector dp(n + 1, std::vector<long long>(2, -INF));
    dp[0][0] = dp[1][1] = 0;

    for (int i = 0; i + 1 < n; i++) {
        std::vector ndp(n + 1, std::vector<long long>(2, -INF));
        for (int j = 0; j <= n; j++) {
            for (int k = 0; k < 2; k++) {
                if (dp[j][k] == -INF) continue;
                // とる
                if (k == 0 || a[i] != 0) {
                    ndp[j + 1][1] = std::max(ndp[j + 1][1], dp[j][k] + k * a[i]);
                }
                // とらない
                ndp[j][0] = std::max(ndp[j][0], dp[j][k]);
            }
        }
        dp = std::move(ndp);
    }
    std::vector<std::pair<int, long long>> result;
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j < 2; j++) {
            if (dp[i][j] == -INF) continue;
            result.emplace_back(i, dp[i][j]);
        }
    }

    // std::cerr << " == cost == " << std::endl;
    // for (auto v: a) std::cerr << v << ' ';
    // std::cerr << std::endl;
    // std::cerr << " == dp == " << std::endl;
    // for (int i = 0; i <= n; i++) {
    //     std::cerr << std::max(dp[i][0], dp[i][1]) << ' ';
    // }
    // std::cerr << std::endl;
    // std::cerr << std::endl;

    return result;
}

std::vector<std::pair<int, long long>> cycle(const std::vector<long long>& a) {
    // n: 頂点数
    int n = a.size();

    std::vector<long long> max_power(n + 1, -INF);
    for (int loop = 0; loop < 2; loop++) {
        std::vector dp(n + 1, std::vector<long long>(2, -INF));
        dp[loop][loop] = 0;
        for (int i = 0; i + 1 < n; i++) {
            std::vector ndp(n + 1, std::vector<long long>(2, -INF));
            for (int j = 0; j <= n; j++) {
                for (int k = 0; k < 2; k++) {
                    if (dp[j][k] == -INF) continue;
                    // とる
                    if (k == 0 || a[i] != 0) {
                        ndp[j + 1][1] = std::max(ndp[j + 1][1], dp[j][k] + k * a[i]);
                    }
                    // とらない
                    ndp[j][0] = std::max(ndp[j][0], dp[j][k]);
                }
            }
            dp = std::move(ndp);
        }
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j < 2; j++) {
                if (loop == 1 && j == 1 && a.back() == 0) continue;
                if (dp[i][j] == -INF) continue;
                max_power[i] = std::max(max_power[i], dp[i][j] + j * loop * a.back());
            }
        }
    }
    std::vector<std::pair<int, long long>> result;
    for (int i = 0; i <= n; i++) {
        if (max_power[i] != -INF) result.emplace_back(i, max_power[i]);
    }
    // std::cerr << " == cost == " << std::endl;
    // for (auto v: a) std::cerr << v << ' ';
    // std::cerr << std::endl;
    // std::cerr << " == dp == " << std::endl;
    // for (int i = 0; i <= n; i++) {
    //     std::cerr << max_power[i] << ' ';
    // }
    // std::cerr << std::endl;
    // std::cerr << std::endl;
    return result;
}

int main() {
    int n, m, k;
    std::cin >> n >> m >> k;
    std::vector<int> degree(n);
    std::vector graph(n, std::vector<std::pair<int, long long>>());
    for (int i = 0; i < m; i++) {
        int u, v;
        long long w;
        std::cin >> u >> v >> w;
        u--; v--;
        degree[u]++;
        degree[v]++;
        graph[u].emplace_back(v, w);
        graph[v].emplace_back(u, w);
    }
    std::vector<std::vector<std::pair<int, long long>>> sets;
    std::vector<bool> used(n);

    std::vector<long long> costs;
    auto dfs = [&](auto self, int u, int p) -> void {
        if (used[u]) return;
        used[u] = true;
        for (auto [v, w]: graph[u]) {
            if (v == p) continue;
            costs.push_back(w);
            self(self, v, u);
            return;
        }
    };

    for (int i = 0; i < n; i++) {
        if (used[i]) continue;
        if (degree[i] == 2) continue;
        if (degree[i] == 0) continue;
        costs.clear();
        dfs(dfs, i, -1);
        sets.push_back(path(costs));
    }
    for (int i = 0; i < n; i++) {
        if (used[i]) continue;
        if (degree[i] == 2) {
            costs.clear();
            dfs(dfs, i, -1);
            sets.push_back(cycle(costs));
        } else {
            assert(degree[i] == 0);
            sets.push_back(std::vector<std::pair<int, long long>>(1, {1, 0}));
        }
    }

    std::vector<long long> dp(n + 1, -INF);
    dp[0] = 0;
    for (const auto& set: sets) {
        std::vector<long long> ndp(n + 1, -INF);
        for (auto [num, val]: set) {
            for (int i = 0; i <= n; i++) {
                if (dp[i] != -INF && i + num <= n) {
                    ndp[i + num] = std::max(ndp[i + num], dp[i] + val);
                }
                ndp[i] = std::max(ndp[i], dp[i]);
            }
        }
        dp = std::move(ndp);
    }

    if (dp[k] == -INF) {
        std::cout << "Impossible" << std::endl;
    } else {
        std::cout << dp[k] << std::endl;
    }
}
accuracy: 1
time_ms: 230
memory_kb: 3812
final_rank: 4

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

const long long INF = 1e18;
std::vector<std::pair<int, long long>> path(const std::vector<long long>& a) {
    int n = a.size() + 1;
    std::vector dp(n + 1, std::vector<long long>(2, -INF));
    dp[0][0] = dp[1][1] = 0;

    for (int i = 0; i + 1 < n; i++) {
        std::vector ndp(n + 1, std::vector<long long>(2, -INF));
        for (int j = 0; j <= n; j++) {
            for (int k = 0; k < 2; k++) {
                if (dp[j][k] == -INF) continue;

                if (k == 0 || a[i] != 0) {
                    ndp[j + 1][1] = std::max(ndp[j + 1][1], dp[j][k] + k * a[i]);
                }

                ndp[j][0] = std::max(ndp[j][0], dp[j][k]);
            }
        }
        dp = std::move(ndp);
    }
    std::vector<std::pair<int, long long>> result;
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j < 2; j++) {
            if (dp[i][j] == -INF) continue;
            result.emplace_back(i, dp[i][j]);
        }
    }

    return result;
}

std::vector<std::pair<int, long long>> cycle(const std::vector<long long>& a) {
    int n = a.size();

    std::vector<long long> max_power(n + 1, -INF);
    for (int loop = 0; loop < 2; loop++) {
        std::vector dp(n + 1, std::vector<long long>(2, -INF));
        dp[loop][loop] = 0;
        for (int i = 0; i + 1 < n; i++) {
            std::vector ndp(n + 1, std::vector<long long>(2, -INF));
            for (int j = 0; j <= n; j++) {
                for (int k = 0; k < 2; k++) {
                    if (dp[j][k] == -INF) continue;

                    if (k == 0 || a[i] != 0) {
                        ndp[j + 1][1] = std::max(ndp[j + 1][1], dp[j][k] + k * a[i]);
                    }

                    ndp[j][0] = std::max(ndp[j][0], dp[j][k]);
                }
            }
            dp = std::move(ndp);
        }
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j < 2; j++) {
                if (loop == 1 && j == 1 && a.back() == 0) continue;
                if (dp[i][j] == -INF) continue;
                max_power[i] = std::max(max_power[i], dp[i][j] + j * loop * a.back());
            }
        }
    }
    std::vector<std::pair<int, long long>> result;
    for (int i = 0; i <= n; i++) {
        if (max_power[i] != -INF) result.emplace_back(i, max_power[i]);
    }

    return result;
}

int main() {
    int n, m, k;
    std::cin >> n >> m >> k;
    std::vector<int> degree(n);
    std::vector graph(n, std::vector<std::pair<int, long long>>());
    for (int i = 0; i < m; i++) {
        int u, v;
        long long w;
        std::cin >> u >> v >> w;
        u--;
        v--;
        degree[u]++;
        degree[v]++;
        graph[u].emplace_back(v, w);
        graph[v].emplace_back(u, w);
    }
    std::vector<std::vector<std::pair<int, long long>>> sets;
    std::vector<bool> used(n);

    std::vector<long long> costs;
    auto dfs = [&](auto self, int u, int p) -> void {
        if (used[u]) return;
        used[u] = true;
        for (auto [v, w]: graph[u]) {
            if (v == p) continue;
            costs.push_back(w);
            self(self, v, u);
            return;
        }
    };

    for (int i = 0; i < n; i++) {
        if (used[i]) continue;
        if (degree[i] == 2) continue;
        if (degree[i] == 0) continue;
        costs.clear();
        dfs(dfs, i, -1);
        sets.push_back(path(costs));
    }
    for (int i = 0; i < n; i++) {
        if (used[i]) continue;
        if (degree[i] == 2) {
            costs.clear();
            dfs(dfs, i, -1);
            sets.push_back(cycle(costs));
        } else {
            sets.push_back(std::vector<std::pair<int, long long>>(1, {1, 0}));
        }
    }

    std::vector<long long> dp(n + 1, -INF);
    dp[0] = 0;
    for (const auto& set: sets) {
        std::vector<long long> ndp(n + 1, -INF);
        for (auto [num, val]: set) {
            for (int i = 0; i <= n; i++) {
                if (dp[i] != -INF && i + num <= n) {
                    ndp[i + num] = std::max(ndp[i + num], dp[i] + val);
                }
            }
        }
        dp = std::move(ndp);
    }

    if (dp[k] == -INF) {
        std::cout << "Impossible" << std::endl;
    } else {
        std::cout << dp[k] << std::endl;
    }
}
accuracy: 0.5348837209302325
time_ms: 220
memory_kb: 3912
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct edge {
  ll to, cost;
};
#define MAX 2005
ll inf = 20000000;
ll INF = inf * 3000LL;
int N, M, K;
vector<edge> G[MAX];
ll DP[MAX][MAX];
ll dp[MAX][MAX][2];
ll V[MAX];
bool visited[MAX];
vector<ll> A, B;
void calc(bool flg) {
  int size = A.size();
  for (int i = 0; i < size; i++)
    for (int j = 0; j <= size; j++)
      for (int k = 0; k < 2; k++)
        dp[i][j][k] = -INF;
  dp[0][flg][flg] = 0;
  for (int i = 1; i < size; i++) {
    for (int j = 0; j <= size; j++) {
      dp[i][j][0] = max(dp[i - 1][j][1], dp[i - 1][j][0]);
      if (j == 0)
        continue;
      ll cost = max(dp[i - 1][j - 1][0], dp[i - 1][j - 1][1] + B[i - 1]);
      if (i + 1 == size && A.size() == B.size() && flg) {
        cost += B[i];
      }
      dp[i][j][1] = max(dp[i][j][1], cost);
    }
  }
  for (int i = 0; i < size; i++)
    for (int j = 0; j <= size; j++)
      for (int k = 0; k < 2; k++)
        V[j] = max(V[j], dp[i][j][k]);
}
void dfs(int pos, int prev) {
  if (visited[pos])
    return;
  visited[pos] = true;
  A.push_back(pos);
  for (int i = 0; i < (int)G[pos].size(); i++) {
    if (G[pos][i].to == prev)
      continue;
    B.push_back(G[pos][i].cost);
    dfs(G[pos][i].to, pos);
    break;
  }
}
int search(int p) {
  map<int, bool> mp;
  while (!mp[p]) {
    mp[p] = true;
    for (int i = 0; i < (int)G[p].size(); i++) {
      edge e = G[p][i];
      if (mp[e.to])
        continue;
      p = e.to;
      break;
    }
  }
  return p;
}
int main() {
  cin >> N >> M >> K;
  for (int i = 0; i < M; i++) {
    ll a, b, c;
    cin >> a >> b >> c;
    if (c == 0)
      c = -INF;
    G[a].push_back((edge){b, c});
    G[b].push_back((edge){a, c});
  }
  for (int i = 0; i < MAX; i++)
    for (int j = 0; j < MAX; j++)
      DP[i][j] = -INF;
  DP[0][0] = 0;
  int C = 0;
  for (int i = 1; i <= N; i++) {
    if (visited[i])
      continue;
    A.clear();
    B.clear();
    dfs(search(i), 0);
    int size = A.size();
    for (int j = 0; j <= size; j++)
      V[j] = -INF;
    calc(true);
    calc(false);
    C++;
    for (int j = 0; j <= K; j++)
      for (int k = 0; k <= min(j, size); k++)
        DP[C][j] = max(DP[C][j], DP[C - 1][j - k] + V[k]);
  }
  if (DP[C][K] < -inf)
    cout << "Impossible" << endl;
  else
    cout << DP[C][K] << endl;
  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 97596
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct edge {
  ll to, cost;
};
#define MAX 2005
ll inf = 20000000;
ll INF = inf * 3000LL;
int N, M, K;
vector<edge> G[MAX];
ll DP[MAX][MAX];
ll dp[MAX][MAX][2];
ll V[MAX];
bool visited[MAX];
vector<ll> A, B;
void calc(bool flg) {
  int size = A.size();
  dp[0][1 - flg][1 - flg] = -INF;
  dp[0][flg][flg] = 0;
  for (int i = 1; i < size; i++) {
    for (int j = 0; j <= size; j++) {
      dp[i][j][0] = max(dp[i - 1][j][1], dp[i - 1][j][0]);
      V[j] = max(V[j], dp[i][j][0]);
      if (j == 0)
        continue;
      ll cost = max(dp[i - 1][j - 1][0], dp[i - 1][j - 1][1] + B[i - 1]);
      if (i + 1 == size && A.size() == B.size() && flg) {
        cost += B[i];
      }
      dp[i][j][1] = cost;
      V[j] = max(V[j], dp[i][j][1]);
    }
  }
}
void dfs(int pos, int prev) {
  if (visited[pos])
    return;
  visited[pos] = true;
  A.push_back(pos);
  for (int i = 0; i < (int)G[pos].size(); i++) {
    if (G[pos][i].to == prev)
      continue;
    B.push_back(G[pos][i].cost);
    dfs(G[pos][i].to, pos);
    break;
  }
}
int search(int p) {
  map<int, bool> mp;
  while (!mp[p]) {
    mp[p] = true;
    for (int i = 0; i < (int)G[p].size(); i++) {
      edge e = G[p][i];
      if (!mp[e.to]) {
        p = e.to;
        break;
      }
    }
  }
  return p;
}
int main() {
  cin >> N >> M >> K;
  for (int i = 0; i < M; i++) {
    ll a, b, c;
    cin >> a >> b >> c;
    if (c == 0)
      c = -INF;
    G[a].push_back((edge){b, c});
    G[b].push_back((edge){a, c});
  }
  for (int i = 0; i < MAX; i++)
    for (int j = 0; j < MAX; j++)
      DP[i][j] = dp[i][j][0] = dp[i][j][1] = -INF;
  DP[0][0] = 0;
  int C = 0;
  for (int i = 1; i <= N; i++) {
    if (visited[i])
      continue;
    A.clear();
    B.clear();
    dfs(search(i), 0);
    int size = A.size();
    fill(V, V + MAX, -INF);
    V[0] = V[1] = 0;
    calc(true);
    calc(false);
    C++;
    for (int j = 0; j <= K; j++)
      for (int k = 0; k <= min(j, size); k++)
        DP[C][j] = max(DP[C][j], DP[C - 1][j - k] + V[k]);
  }
  if (DP[C][K] < -inf)
    cout << "Impossible" << endl;
  else
    cout << DP[C][K] << endl;
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 97720
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
using pii = pair<int, int>;
#define rep(i, x) for(int i = 0; i < (x); i++)
#define rng(i, l, r) for(int i = (l); i < (r); i++)
#define all(v) (v).begin(), (v).end()
#define sz(v) (int)(v).size()
const int inf = 1 << 29;

void chmax(int &x, int y) {
	x = x < y ? y : x;
}

int main() {
	int n, m, k;
	cin >> n >> m >> k;
	vector<vi> g(n);
	vi in(n);
	vector<vi> dist(n, vi(n, -inf));
	rep(i, m) {
		int u, v, c;
		cin >> u >> v >> c, --u, --v;
		g[u].emplace_back(v);
		g[v].emplace_back(u);
		dist[u][v] = dist[v][u] = c;
		in[u]++, in[v]++;
	}
	vector dp_all(n + 1, -inf);
	int zero = count(all(in), 0);
	rep(i, zero + 1) dp_all[i] = 0;
	int sum = zero;
	vector<int> vis(n);
	rep(i, n) {
		if(in[i] == 1 and !vis[i]) {
			vi path;
			auto get_path = [&](auto self, int v) -> void {
				if(vis[v]) return;
				vis[v] = 1;
				path.push_back(v);
				for(auto to : g[v]) self(self, to);
			};
			get_path(get_path, i);
			int len = sz(path);
			vector dp(len + 1, vector(2, -inf));
			dp[0][0] = 0;
			dp[1][1] = 0;
			rng(i, 1, len) {
				vector ndp(len + 1, vector(2, -inf));
				rep(j, i + 1) {
					rep(f, 2) {
						rep(nx, 2) {
							int bef = path[i - 1];
							int now = path[i];
							int val = dp[j][f];
							if(f and nx) {
								if(dist[bef][now] == 0)
									val = -inf;
								else
									val += dist[bef][now];
							}
							chmax(ndp[j + nx][nx], val);
						}
					}
				}
				dp = ndp;
			}
			auto ndp = dp_all;
			for(int i = sum; i >= 0; --i) {
				rep(j, len + 1) {
					chmax(ndp[i + j], dp_all[i] + max(dp[j][0], dp[j][1]));
				}
			}
			dp_all = move(ndp);
			sum += sz(path);
		}
	}
	rep(i, n) {
		if(in[i] == 2 and !vis[i]) {
			vi path;
			auto get_path = [&](auto self, int v) -> void {
				if(vis[v]) return;
				vis[v] = 1;
				path.push_back(v);
				for(auto to : g[v]) self(self, to);
			};
			get_path(get_path, i);
			int len = sz(path);
			vector dp(len + 1, vector(2, vector(2, -inf)));
			dp[0][0][0] = 0;
			dp[1][1][1] = 0;
			rng(i, 1, len) {
				vector ndp(len + 1, vector(2, vector(2, -inf)));
				rep(j, i + 1) {
					rep(f, 2) {
						rep(nx, 2) {
							rep(fi, 2) {
								int bef = path[i - 1];
								int now = path[i];
								int val = dp[j][f][fi];
								if(f and nx) {
									if(dist[bef][now] == 0)
										val = -inf;
									else
										val += dist[bef][now];
								}
								chmax(ndp[j + nx][nx][fi], val);
							}
						}
					}
				}
				dp = move(ndp);
			}
			vi items(len + 1, -inf);
			rep(i, len + 1) {
				rep(t, 2) {
					rep(fi, 2) {
						if(t + fi == 2) {
							if(dist[path[0]][path.back()]) {
								dp[i][t][fi] += dist[path[0]][path.back()];
							} else {
								dp[i][t][fi] = -inf;
							}
						}
						chmax(items[i], dp[i][t][fi]);
					}
				}
			}
			auto ndp = dp_all;
			for(int i = sum; i >= 0; --i) {
				rep(j, len + 1) {
					if(dp_all[i] != -inf and items[j] != -inf)
						chmax(ndp[i + j], dp_all[i] + items[j]);
				}
			}
			dp_all = move(ndp);
			sum += sz(path);
		}
	}
	if(dp_all[k] <= -inf / 2)
		cout << "Impossible\n";
	else
		cout << dp_all[k] << endl;
}
accuracy: 1
time_ms: 360
memory_kb: 19820
final_rank: 8

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

struct UnionFind{
    vector<int> par,num;
    vector<bool> done;
    UnionFind(int n):par(n),num(n,1),done(n,false){
        iota(par.begin(),par.end(),0);  //include<numeric>
    }
    int find(int v){
        return (par[v]==v)?v:(par[v]=find(par[v]));
    }
    void unite(int u,int v){
        u=find(u),v=find(v);
        if(u==v)return;
        if(num[u]<num[v])swap(u,v);
        num[u]+=num[v];
        par[v]=u;
        done[u]=done[u]|done[v];
    }
    bool same(int u,int v){
        return find(u) == find(v);
    }
    int size(int v){
        return num[find(v)];
    }
};

int dp[2001][2001];

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    const int inf = 1e9;
    int n,m,k; cin >> n >> m >> k;
    vector<vector<pair<int,int>>> g(n);
    UnionFind uf(n);
    for(int i=0;i<m;i++){
        int x,y,c; cin >> x >> y >> c;
        x--; y--;
        g[x].push_back({y,c});
        g[y].push_back({x,c});
        if(uf.same(x,y)){
            uf.done[uf.find(x)] = true;
        }
        else uf.unite(x, y);
    }
    vector<bool> used(n,false);
    vector<vector<int>> v;
    for(int i=0;i<n;i++){
        if(used[uf.find(i)]) continue;
        // 孤立点
        if(g[i].size() == 0){
            v.push_back({0,0}); continue;
        }
        // 鎖の端
        if(g[i].size() == 1){
            used[uf.find(i)] = true;
            int f = i;
            int cur = f;
            int pre = -1;
            vector<int> cost;
            do{
                bool ff = false;
                for(auto t:g[cur]){
                    if(t.first != pre){
                        cost.push_back(t.second);
                        pre = cur;
                        cur = t.first;
                        ff = true;
                        break;
                    }
                }
                if(!ff)break;
            }while(1);
            int sz = cost.size()+1;
            vector<int> res(sz+1,-inf);
            res[0] = res[1] = 0;
            {
                for(int i=0;i<=sz;i++){
                    for(int j=0;j<sz;j++){
                        dp[i][j] = -inf;
                    }
                }
                for(int i=0;i<sz;i++){
                    dp[1][i] = 0;
                }
                for(int i=1;i<=sz;i++){
                    for(int j=0;j<sz;j++){
                        if(dp[i][j] == -inf)continue;
                        res[i] = max(res[i], dp[i][j]);
                        for(int k=j+1;k<sz;k++){
                            if(j+1 == k and cost[j] == 0) continue;
                            dp[i+1][k] = max(dp[i+1][k], dp[i][j]+(j+1==k?cost[j]:0));
                        }
                    }
                }
            }
            v.push_back(res);
            continue;
        }
        // 輪
        if(uf.done[uf.find(i)]){
            used[uf.find(i)] = true;
            int f = i;
            int cur = f;
            int pre = -1;
            vector<int> cost;
            do{
                for(auto t:g[cur]){
                    if(t.first != pre){
                        cost.push_back(t.second);
                        pre = cur;
                        cur = t.first;
                        break;
                    }
                }
            }while(cur != f);

            int sz = cost.size();
            vector<int> res(sz+1,-inf);
            res[0] = res[1] = 0;
            // 最初を使う場合
            {
                for(int i=0;i<=sz;i++){
                    for(int j=0;j<sz;j++){
                        dp[i][j] = -inf;
                    }
                }
                dp[1][0] = 0;
                for(int i=1;i<=sz;i++){
                    for(int j=0;j<sz;j++){
                        if(dp[i][j] == -inf)continue;
                        res[i] = max(res[i], dp[i][j]);
                        for(int k=j+1;k<sz;k++){
                            if(k+1 == sz and cost.back() == 0) continue;
                            if(j+1 == k and cost[j] == 0) continue;
                            dp[i+1][k] = max(dp[i+1][k], dp[i][j]+(j+1==k?cost[j]:0)+(k+1==sz?cost.back():0));
                        }
                    }
                }
            }
            // 最初を使わない場合
            {
                for(int i=0;i<=sz;i++){
                    for(int j=0;j<sz;j++){
                        dp[i][j] = -inf;
                    }
                }
                for(int i=1;i<sz;i++){
                    dp[1][i] = 0;
                }
                for(int i=1;i<=sz;i++){
                    for(int j=0;j<sz;j++){
                        if(dp[i][j] == -inf)continue;
                        res[i] = max(res[i], dp[i][j]);
                        for(int k=j+1;k<sz;k++){
                            if(j+1 == k and cost[j] == 0) continue;
                            dp[i+1][k] = max(dp[i+1][k], dp[i][j]+(j+1==k?cost[j]:0));
                        }
                    }
                }
            }
            v.push_back(res);
            continue;
        }
    }
    n = v.size();
    vector<vector<int>> dp(n+1,vector<int>(k+1,-inf));
    dp[0][0] = 0;
    for(int i=0;i<n;i++){
        for(int j=0;j<v[i].size();j++){
            for(int p=0;p+j<=k;p++){
                if(dp[i][p] == -inf)continue;
                dp[i+1][p+j] = max(dp[i+1][p+j], dp[i][p]+v[i][j]);
            }
        }
    }
    if(dp[n][k] == -inf){
        cout << "Impossible" << endl;
    }
    else{
        cout << dp[n][k] << endl;
    }
}
accuracy: 1
time_ms: 1740
memory_kb: 19272
final_rank: 12

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

struct UnionFind{
    vector<int> par,num;
    vector<bool> done;
    UnionFind(int n):par(n),num(n,1),done(n,false){
        iota(par.begin(),par.end(),0);  //include<numeric>
    }
    int find(int v){
        return (par[v]==v)?v:(par[v]=find(par[v]));
    }
    void unite(int u,int v){
        u=find(u),v=find(v);
        if(u==v)return;
        if(num[u]<num[v])swap(u,v);
        num[u]+=num[v];
        par[v]=u;
        done[u]=done[u]|done[v];
    }
    bool same(int u,int v){
        return find(u) == find(v);
    }
    int size(int v){
        return num[find(v)];
    }
};


int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    const int inf = 1e9;
    int n,m,k; cin >> n >> m >> k;
    vector<vector<pair<int,int>>> g(n);
    UnionFind uf(n);
    for(int i=0;i<m;i++){
        int x,y,c; cin >> x >> y >> c;
        x--; y--;
        g[x].push_back({y,c});
        g[y].push_back({x,c});
        if(uf.same(x,y)){
            uf.done[uf.find(x)] = true;
        }
        else uf.unite(x, y);
    }
    vector<bool> used(n,false);
    vector<vector<int>> v;
    for(int i=0;i<n;i++){
        if(used[uf.find(i)]) continue;
        // 孤立点
        if(g[i].size() == 0){
            v.push_back({0,0}); continue;
        }
        // 鎖の端
        if(g[i].size() == 1){
            used[uf.find(i)] = true;
            int f = i;
            int cur = f;
            int pre = -1;
            vector<int> cost;
            do{
                bool ff = false;
                for(auto t:g[cur]){
                    if(t.first != pre){
                        cost.push_back(t.second);
                        pre = cur;
                        cur = t.first;
                        ff = true;
                        break;
                    }
                }
                if(!ff)break;
            }while(1);
            int sz = cost.size()+1;
            vector<int> res(sz+1,-inf);
            res[0] = res[1] = 0;
            {
                vector<vector<int>> dp(sz+1,vector<int>(sz,-inf));
                for(int i=0;i<sz;i++){
                    dp[1][i] = 0;
                }
                for(int i=1;i<=sz;i++){
                    for(int j=0;j<sz;j++){
                        if(dp[i][j] == -inf)continue;
                        res[i] = max(res[i], dp[i][j]);
                        for(int k=j+1;k<sz;k++){
                            if(j+1 == k and cost[j] == 0) continue;
                            dp[i+1][k] = max(dp[i+1][k], dp[i][j]+(j+1==k?cost[j]:0));
                        }
                    }
                }
            }
            v.push_back(res);
            continue;
        }
        // 輪
        if(uf.done[uf.find(i)]){
            used[uf.find(i)] = true;
            int f = i;
            int cur = f;
            int pre = -1;
            vector<int> cost;
            do{
                for(auto t:g[cur]){
                    if(t.first != pre){
                        cost.push_back(t.second);
                        pre = cur;
                        cur = t.first;
                        break;
                    }
                }
            }while(cur != f);

            int sz = cost.size();
            vector<int> res(sz+1,-inf);
            res[0] = res[1] = 0;
            // 最初を使う場合
            {
                vector<vector<int>> dp(sz+1,vector<int>(sz,-inf));
                dp[1][0] = 0;
                for(int i=1;i<=sz;i++){
                    for(int j=0;j<sz;j++){
                        if(dp[i][j] == -inf)continue;
                        res[i] = max(res[i], dp[i][j]);
                        for(int k=j+1;k<sz;k++){
                            if(k+1 == sz and cost.back() == 0) continue;
                            if(j+1 == k and cost[j] == 0) continue;
                            dp[i+1][k] = max(dp[i+1][k], dp[i][j]+(j+1==k?cost[j]:0)+(k+1==sz?cost.back():0));
                        }
                    }
                }
            }
            // 最初を使わない場合
            {
                vector<vector<int>> dp(sz+1,vector<int>(sz,-inf));
                for(int i=1;i<sz;i++){
                    dp[1][i] = 0;
                }
                for(int i=1;i<=sz;i++){
                    for(int j=0;j<sz;j++){
                        if(dp[i][j] == -inf)continue;
                        res[i] = max(res[i], dp[i][j]);
                        for(int k=j+1;k<sz;k++){
                            if(j+1 == k and cost[j] == 0) continue;
                            dp[i+1][k] = max(dp[i+1][k], dp[i][j]+(j+1==k?cost[j]:0));
                        }
                    }
                }
            }
            v.push_back(res);
            continue;
        }
    }
    n = v.size();
    vector<vector<int>> dp(n+1,vector<int>(k+1,-inf));
    dp[0][0] = 0;
    for(int i=0;i<n;i++){
        for(int j=0;j<v[i].size();j++){
            for(int p=0;p+j<=k;p++){
                if(dp[i][p] == -inf)continue;
                dp[i+1][p+j] = max(dp[i+1][p+j], dp[i][p]+v[i][j]);
            }
        }
    }
    if(dp[n][k] == -inf){
        cout << "Impossible" << endl;
    }
    else{
        cout << dp[n][k] << endl;
    }
}
accuracy: 1
time_ms: 2170
memory_kb: 19032
final_rank: 15

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

struct UnionFind{
    vector<int> par,num;
    vector<bool> done;
    UnionFind(int n):par(n),num(n,1),done(n,false){
        iota(par.begin(),par.end(),0);  //include<numeric>
    }
    int find(int v){
        return (par[v]==v)?v:(par[v]=find(par[v]));
    }
    void unite(int u,int v){
        u=find(u),v=find(v);
        if(u==v)return;
        if(num[u]<num[v])swap(u,v);
        num[u]+=num[v];
        par[v]=u;
        done[u]=done[u]|done[v];
    }
    bool same(int u,int v){
        return find(u) == find(v);
    }
    int size(int v){
        return num[find(v)];
    }
};


int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    const int inf = 1e9;
    int n,m,k; cin >> n >> m >> k;
    vector<vector<pair<int,int>>> g(n);
    UnionFind uf(n);
    for(int i=0;i<m;i++){
        int x,y,c; cin >> x >> y >> c;
        x--; y--;
        g[x].push_back({y,c});
        g[y].push_back({x,c});
        if(uf.same(x,y)){
            uf.done[uf.find(x)] = true;
        }
        else uf.unite(x, y);
    }
    vector<bool> used(n,false);
    vector<vector<int>> v;
    for(int i=0;i<n;i++){
        if(used[uf.find(i)]) continue;
        // 孤立点
        if(g[i].size() == 0){
            v.push_back({0,0}); continue;
        }
        // 鎖の端
        if(g[i].size() == 1){
            used[uf.find(i)] = true;
            int f = i;
            int cur = f;
            int pre = -1;
            vector<int> cost;
            do{
                bool ff = false;
                for(auto t:g[cur]){
                    if(t.first != pre){
                        cost.push_back(t.second);
                        pre = cur;
                        cur = t.first;
                        ff = true;
                        break;
                    }
                }
                if(!ff)break;
            }while(1);
            int sz = cost.size()+1;
            vector<int> res(sz+1,-inf);
            {
                vector<vector<int>> dp(sz+1,vector<int>(sz,-inf));
                for(int i=0;i<sz;i++){
                    dp[1][i] = 0;
                }
                for(int i=1;i<=sz;i++){
                    for(int j=0;j<sz;j++){
                        if(dp[i][j] == -inf)continue;
                        res[i] = max(res[i], dp[i][j]);
                        for(int k=j+1;k<sz;k++){
                            if(j+1 == k and cost[j] == 0) continue;
                            dp[i+1][k] = max(dp[i+1][k], dp[i][j]+(j+1==k?cost[j]:0));
                        }
                    }
                }
            }
            v.push_back(res);
            continue;
        }
        // 輪
        if(uf.done[uf.find(i)]){
            used[uf.find(i)] = true;
            int f = i;
            int cur = f;
            int pre = -1;
            vector<int> cost;
            do{
                for(auto t:g[cur]){
                    if(t.first != pre){
                        cost.push_back(t.second);
                        pre = cur;
                        cur = t.first;
                        break;
                    }
                }
            }while(cur != f);

            int sz = cost.size();
            vector<int> res(sz+1,-inf);
            // 最初を使う場合
            {
                vector<vector<int>> dp(sz+1,vector<int>(sz,-inf));
                dp[1][0] = 0;
                for(int i=1;i<=sz;i++){
                    for(int j=0;j<sz;j++){
                        if(dp[i][j] == -inf)continue;
                        res[i] = max(res[i], dp[i][j]);
                        for(int k=j+1;k<sz;k++){
                            if(k+1 == sz and cost.back() == 0) continue;
                            if(j+1 == k and cost[j] == 0) continue;
                            dp[i+1][k] = max(dp[i+1][k], dp[i][j]+(j+1==k?cost[j]:0)+(k+1==sz?cost.back():0));
                        }
                    }
                }
            }
            // 最初を使わない場合
            {
                vector<vector<int>> dp(sz+1,vector<int>(sz,-inf));
                for(int i=1;i<sz;i++){
                    dp[1][i] = 0;
                }
                for(int i=1;i<=sz;i++){
                    for(int j=0;j<sz;j++){
                        if(dp[i][j] == -inf)continue;
                        res[i] = max(res[i], dp[i][j]);
                        for(int k=j+1;k<sz;k++){
                            if(j+1 == k and cost[j] == 0) continue;
                            dp[i+1][k] = max(dp[i+1][k], dp[i][j]+(j+1==k?cost[j]:0));
                        }
                    }
                }
            }
            v.push_back(res);
            continue;
        }
    }
    n = v.size();
    vector<vector<int>> dp(n+1,vector<int>(k+1,-inf));
    dp[0][0] = 0;
    for(int i=0;i<n;i++){
        for(int j=0;j<v[i].size();j++){
            for(int p=0;p+j<=k;p++){
                if(dp[i][p] == -inf)continue;
                dp[i+1][p+j] = max(dp[i+1][p+j], dp[i][p]+v[i][j]);
            }
        }
    }
    if(dp[n][k] == -inf){
        cout << "Impossible" << endl;
    }
    else{
        cout << dp[n][k] << endl;
    }
}
accuracy: 0.6046511627906976
time_ms: 2170
memory_kb: 19068
final_rank: 16

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

using namespace std;

#define eps 1e-9
#define INF 2000000000              // 2e9
#define LLINF 2000000000000000000ll // 2e18 (llmax:9e18)
#define all(x) (x).begin(), (x).end()
#define sq(x) ((x) * (x))

#define rep(i, x) for (int i = 0; i < (int)(x); i++)
#define drep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)

#define popcount __builtin_popcount
#define next __next
#define prev __prev

#ifndef LOCAL
#define dmp(...) ;
#else
#define dmp(...)                                                               \
  cerr << "[ " << #__VA_ARGS__ << " ] : " << dump_str(__VA_ARGS__) << endl
#endif

// ---------------- Utility ------------------

template <class T>
bool chmin(T &a, const T &b) {
  if (a <= b) return false;
  a = b;
  return true;
}

template <class T>
bool chmax(T &a, const T &b) {
  if (a >= b) return false;
  a = b;
  return true;
}

template <class T>
using MaxHeap = priority_queue<T>;

template <class T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;

template <class T>
vector<T> vect(int len, T elem) {
  return vector<T>(len, elem);
}

// ----------------- Input -------------------

template <class T, class U>
istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}

template <class T>
istream &operator>>(istream &is, vector<T> &vec) {
  for (int i = 0; i < vec.size(); i++) is >> vec[i];
  return is;
}

// ----------------- Output ------------------

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ',' << p.second;
}

template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (const T &e : v) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const deque<T> &d) {
  for (const T &e : d) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const set<T> &s) {
  os << "{ ";
  for (const T &e : s) os << e << " ";
  return os << "}";
}

template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &m) {
  os << "{ ";
  for (const auto &[key, val] : m) os << "( " << key << " -> " << val << " ) ";
  return os << "}";
}

template <class TupleTy, size_t... I>
void dump_tuple(ostream &os, const TupleTy t, std::index_sequence<I...>) {
  (..., (os << (I == 0 ? "" : ",") << std::get<I>(t)));
}

template <class... Args>
ostream &operator<<(ostream &os, const tuple<Args...> &t) {
  os << "(";
  dump_tuple(os, t, std::make_index_sequence<sizeof...(Args)>());
  return os << ")";
}

void dump_str_rec(ostringstream &) {}

template <class Head, class... Tail>
void dump_str_rec(ostringstream &oss, Head &&head, Tail &&... tail) {
  oss << ", " << head;
  dump_str_rec(oss, forward<Tail>(tail)...);
}

template <class T, class... U>
string dump_str(T &&arg, U &&... args) {
  ostringstream oss;
  oss << arg;
  dump_str_rec(oss, forward<U>(args)...);
  return oss.str();
}

// --------------- Fast I/O ------------------

void fastio() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout << fixed << setprecision(20);
}

// ------------------ ACL --------------------

// #include <atcoder/modint>
// constexpr int MOD = 998244353;
// constexpr int MOD = 1000000007;
// using mint = atcoder::static_modint<MOD>;
// ostream &operator<<(ostream &os, const mint &v) {
//   return os << v.val();
// }

// ------------ End of template --------------

#define endl "\n"
using ll = long long;
using pii = pair<int, int>;

const bool multitest = false;

void solve() {
  int N, M, K;
  cin >> N >> M >> K;
  vector<int> a(M), b(M), c(M);
  auto match = vect(N, vect(N, 0));
  auto ban = vect(N, vect(N, false));
  vector<vector<int>> g(N);
  for (int i = 0; i < M; i++) {
    cin >> a[i] >> b[i] >> c[i];
    a[i]--;
    b[i]--;
    if (c[i] == 0) {
      ban[a[i]][b[i]] = ban[b[i]][a[i]] = true;
      // match[a[i]][b[i]] = match[b[i]][a[i]] = -INF;
    } else {
      match[a[i]][b[i]] = match[b[i]][a[i]] = c[i];
    }
    g[a[i]].push_back(b[i]);
    g[b[i]].push_back(a[i]);
  }

  vector<int> path;
  vector<int> group_id(N, -1);
  vector<bool> group_begin(N, false);
  vector<int> group_first;
  vector<bool> group_end(N, false);

  function<void(int, int)> dfs = [&](int v, int g_id) {
    group_id[v] = g_id;
    path.push_back(v);
    for (int u : g[v]) {
      if (group_id[u] == -1) dfs(u, g_id);
    }
  };

  int cycle_id_min = INF;
  {
    int k = 0;
    for (int i = 0; i < N; i++) {
      if (group_id[i] == -1 && g[i].size() == 1) {
        group_begin[i] = true;
        group_first.push_back(i);
        dfs(i, k++);
        group_end[path.back()] = true;
      }
    }
    cycle_id_min = k;
    for (int i = 0; i < N; i++) {
      if (group_id[i] == -1) {
        group_begin[i] = true;
        group_first.push_back(i);
        dfs(i, k++);
        group_end[path.back()] = true;
      }
    }

    dmp(path);
    dmp(group_id);
    dmp(group_begin);
    dmp(group_end);
    dmp(group_first);
    dmp(cycle_id_min);
    dmp(k);
  }

  auto dp = vect(N + 1, vect(2, vect(2, vect(N + 1, -INF))));
  dp[0][0][0][0] = 0;
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        for (int l = 0; l <= N; l++) {
          if (dp[i][j][k][l] == -INF) continue;
          int v = path[i];
          if (group_begin[v]) {
            chmax(dp[i + 1][0][0][l], dp[i][j][k][l]);
            chmax(dp[i + 1][1][1][l + 1], dp[i][j][k][l]);
          } else if (group_end[v] && group_id[v] >= cycle_id_min) {
            chmax(dp[i + 1][j][0][l], dp[i][j][k][l]);
            int u = path[i - 1];
            assert(group_id[u] == group_id[v]);
            int g_first = group_first[group_id[v]];
            assert(u != g_first);
            bool ban_prev = (k == 1) && ban[u][v];
            bool ban_first = (j == 1) && ban[v][g_first];
            if (!ban_prev && !ban_first) {
              int up = 0;
              if (k == 1) up += match[u][v];
              if (j == 1) up += match[v][g_first];
              chmax(dp[i + 1][j][1][l + 1], dp[i][j][k][l] + up);
            }
          } else {
            int u = path[i - 1];
            chmax(dp[i + 1][j][0][l], dp[i][j][k][l]);
            if (k == 0 || !ban[u][v]) {
              int up = (k == 0) ? 0 : match[u][v];
              chmax(dp[i + 1][j][1][l + 1], dp[i][j][k][l] + up);
            }
          }
        }
      }
    }
  }

  int ans = -INF;
  for (int j = 0; j < 2; j++) {
    for (int k = 0; k < 2; k++) { chmax(ans, dp[N][j][k][K]); }
  }

  if (ans == -INF)
    cout << "Impossible" << endl;
  else
    cout << ans << endl;

  return;
}

int main() {
  fastio();
  if (!multitest) {
    solve();
  } else {
    cerr << "[Warning] Multi testcase mode on" << endl;
    int t;
    cin >> t;
    while (t--) solve();
  }
  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 82816
final_rank: 11

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

using namespace std;

#define eps 1e-9
#define INF 2000000000              // 2e9
#define LLINF 2000000000000000000ll // 2e18 (llmax:9e18)
#define all(x) (x).begin(), (x).end()
#define sq(x) ((x) * (x))

#define rep(i, x) for (int i = 0; i < (int)(x); i++)
#define drep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)

#define popcount __builtin_popcount
#define next __next
#define prev __prev

#ifndef LOCAL
#define dmp(...) ;
#else
#define dmp(...)                                                               \
  cerr << "[ " << #__VA_ARGS__ << " ] : " << dump_str(__VA_ARGS__) << endl
#endif

// ---------------- Utility ------------------

template <class T>
bool chmin(T &a, const T &b) {
  if (a <= b) return false;
  a = b;
  return true;
}

template <class T>
bool chmax(T &a, const T &b) {
  if (a >= b) return false;
  a = b;
  return true;
}

template <class T>
using MaxHeap = priority_queue<T>;

template <class T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;

template <class T>
vector<T> vect(int len, T elem) {
  return vector<T>(len, elem);
}

// ----------------- Input -------------------

template <class T, class U>
istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}

template <class T>
istream &operator>>(istream &is, vector<T> &vec) {
  for (int i = 0; i < vec.size(); i++) is >> vec[i];
  return is;
}

// ----------------- Output ------------------

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ',' << p.second;
}

template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (const T &e : v) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const deque<T> &d) {
  for (const T &e : d) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const set<T> &s) {
  os << "{ ";
  for (const T &e : s) os << e << " ";
  return os << "}";
}

template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &m) {
  os << "{ ";
  for (const auto &[key, val] : m) os << "( " << key << " -> " << val << " ) ";
  return os << "}";
}

template <class TupleTy, size_t... I>
void dump_tuple(ostream &os, const TupleTy t, std::index_sequence<I...>) {
  (..., (os << (I == 0 ? "" : ",") << std::get<I>(t)));
}

template <class... Args>
ostream &operator<<(ostream &os, const tuple<Args...> &t) {
  os << "(";
  dump_tuple(os, t, std::make_index_sequence<sizeof...(Args)>());
  return os << ")";
}

void dump_str_rec(ostringstream &) {}

template <class Head, class... Tail>
void dump_str_rec(ostringstream &oss, Head &&head, Tail &&... tail) {
  oss << ", " << head;
  dump_str_rec(oss, forward<Tail>(tail)...);
}

template <class T, class... U>
string dump_str(T &&arg, U &&... args) {
  ostringstream oss;
  oss << arg;
  dump_str_rec(oss, forward<U>(args)...);
  return oss.str();
}

// --------------- Fast I/O ------------------

void fastio() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout << fixed << setprecision(20);
}

// ------------------ ACL --------------------

// #include <atcoder/modint>
// constexpr int MOD = 998244353;
// constexpr int MOD = 1000000007;
// using mint = atcoder::static_modint<MOD>;
// ostream &operator<<(ostream &os, const mint &v) {
//   return os << v.val();
// }

// ------------ End of template --------------

#define endl "\n"
using ll = long long;
using pii = pair<int, int>;

const bool multitest = false;

void solve() {
  int N, M, K;
  cin >> N >> M >> K;
  vector<int> a(M), b(M), c(M);
  auto match = vect(N, vect(N, 0));
  auto ban = vect(N, vect(N, false));
  vector<vector<int>> g(N);
  for (int i = 0; i < M; i++) {
    cin >> a[i] >> b[i] >> c[i];
    a[i]--;
    b[i]--;
    if (c[i] == 0) {
      ban[a[i]][b[i]] = ban[b[i]][a[i]] = true;
      // match[a[i]][b[i]] = match[b[i]][a[i]] = -INF;
    } else {
      match[a[i]][b[i]] = match[b[i]][a[i]] = c[i];
    }
    g[a[i]].push_back(b[i]);
    g[b[i]].push_back(a[i]);
  }

  vector<int> path;
  vector<int> group_id(N, -1);
  vector<bool> group_begin(N, false);
  vector<bool> group_first;
  vector<bool> group_end(N, false);

  function<void(int, int)> dfs = [&](int v, int g_id) {
    group_id[v] = g_id;
    path.push_back(v);
    for (int u : g[v]) {
      if (group_id[u] == -1) dfs(u, g_id);
    }
  };

  int cycle_id_min = INF;
  {
    int k = 0;
    for (int i = 0; i < N; i++) {
      if (group_id[i] == -1 && g[i].size() == 1) {
        group_begin[i] = true;
        group_first.push_back(i);
        dfs(i, k++);
        group_end[path.back()] = true;
      }
    }
    cycle_id_min = k;
    for (int i = 0; i < N; i++) {
      if (group_id[i] == -1) {
        group_begin[i] = true;
        group_first.push_back(i);
        dfs(i, k++);
        group_end[path.back()] = true;
      }
    }
    dmp(path);
    dmp(group_id);
    dmp(group_end);
    dmp(cycle_id_min);
    dmp(k);
  }

  auto dp = vect(N + 1, vect(2, vect(2, vect(N + 1, -INF))));
  dp[0][0][0][0] = 0;
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        for (int l = 0; l <= N; l++) {
          if (dp[i][j][k][l] == -INF) continue;
          int v = path[i];
          if (group_begin[v]) {
            chmax(dp[i + 1][0][0][l], dp[i][j][k][l]);
            chmax(dp[i + 1][1][1][l + 1], dp[i][j][k][l]);
          } else if (group_end[v] && group_id[v] >= cycle_id_min) {
            chmax(dp[i + 1][j][0][l], dp[i][j][k][l]);
            int u = path[i - 1];
            assert(group_id[u] == group_id[v]);
            int g_first = group_first[group_id[v]];
            assert(u != g_first);
            bool ban_prev = (k == 1) && ban[u][v];
            bool ban_first = (j == 1) && ban[v][g_first];
            if (!ban_prev && !ban_first) {
              int up = 0;
              if (k == 1) up += match[u][v];
              if (j == 1) up += match[v][g_first];
              chmax(dp[i + 1][j][1][l + 1], dp[i][j][k][l] + up);
            }
          } else {
            int u = path[i - 1];
            chmax(dp[i + 1][j][0][l], dp[i][j][k][l]);
            if (k == 0 || !ban[u][v]) {
              int up = (k == 0) ? 0 : match[u][v];
              chmax(dp[i + 1][j][1][l + 1], dp[i][j][k][l] + up);
            }
          }
        }
      }
    }
  }

  int ans = -INF;
  for (int j = 0; j < 2; j++) {
    for (int k = 0; k < 2; k++) { chmax(ans, dp[N][j][k][K]); }
  }

  if (ans == -INF)
    cout << "Impossible" << endl;
  else
    cout << ans << endl;

  return;
}

int main() {
  fastio();
  if (!multitest) {
    solve();
  } else {
    cerr << "[Warning] Multi testcase mode on" << endl;
    int t;
    cin >> t;
    while (t--) solve();
  }
  return 0;
}
accuracy: 0.3488372093023256
time_ms: 50
memory_kb: 82704
final_rank: 19

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

using namespace std;

#define eps 1e-9
#define INF 2000000000              // 2e9
#define LLINF 2000000000000000000ll // 2e18 (llmax:9e18)
#define all(x) (x).begin(), (x).end()
#define sq(x) ((x) * (x))

#define rep(i, x) for (int i = 0; i < (int)(x); i++)
#define drep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)

#define popcount __builtin_popcount
#define next __next
#define prev __prev

#ifndef LOCAL
#define dmp(...) ;
#else
#define dmp(...)                                                               \
  cerr << "[ " << #__VA_ARGS__ << " ] : " << dump_str(__VA_ARGS__) << endl
#endif

// ---------------- Utility ------------------

template <class T>
bool chmin(T &a, const T &b) {
  if (a <= b) return false;
  a = b;
  return true;
}

template <class T>
bool chmax(T &a, const T &b) {
  if (a >= b) return false;
  a = b;
  return true;
}

template <class T>
using MaxHeap = priority_queue<T>;

template <class T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;

template <class T>
vector<T> vect(int len, T elem) {
  return vector<T>(len, elem);
}

// ----------------- Input -------------------

template <class T, class U>
istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}

template <class T>
istream &operator>>(istream &is, vector<T> &vec) {
  for (int i = 0; i < vec.size(); i++) is >> vec[i];
  return is;
}

// ----------------- Output ------------------

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ',' << p.second;
}

template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (const T &e : v) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const deque<T> &d) {
  for (const T &e : d) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const set<T> &s) {
  os << "{ ";
  for (const T &e : s) os << e << " ";
  return os << "}";
}

template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &m) {
  os << "{ ";
  for (const auto &[key, val] : m) os << "( " << key << " -> " << val << " ) ";
  return os << "}";
}

template <class TupleTy, size_t... I>
void dump_tuple(ostream &os, const TupleTy t, std::index_sequence<I...>) {
  (..., (os << (I == 0 ? "" : ",") << std::get<I>(t)));
}

template <class... Args>
ostream &operator<<(ostream &os, const tuple<Args...> &t) {
  os << "(";
  dump_tuple(os, t, std::make_index_sequence<sizeof...(Args)>());
  return os << ")";
}

void dump_str_rec(ostringstream &) {}

template <class Head, class... Tail>
void dump_str_rec(ostringstream &oss, Head &&head, Tail &&... tail) {
  oss << ", " << head;
  dump_str_rec(oss, forward<Tail>(tail)...);
}

template <class T, class... U>
string dump_str(T &&arg, U &&... args) {
  ostringstream oss;
  oss << arg;
  dump_str_rec(oss, forward<U>(args)...);
  return oss.str();
}

// --------------- Fast I/O ------------------

void fastio() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout << fixed << setprecision(20);
}

// ------------------ ACL --------------------

// #include <atcoder/modint>
// constexpr int MOD = 998244353;
// constexpr int MOD = 1000000007;
// using mint = atcoder::static_modint<MOD>;
// ostream &operator<<(ostream &os, const mint &v) {
//   return os << v.val();
// }

// ------------ End of template --------------

#define endl "\n"
using ll = long long;
using pii = pair<int, int>;

const bool multitest = false;

void solve() {
  int N, M, K;
  cin >> N >> M >> K;
  vector<int> a(M), b(M), c(M);
  auto match = vect(N, vect(N, 0));
  auto ban = vect(N, vect(N, false));
  vector<vector<int>> g(N);
  for (int i = 0; i < M; i++) {
    cin >> a[i] >> b[i] >> c[i];
    a[i]--;
    b[i]--;
    if (c[i] == 0)
      ban[a[i]][b[i]] = ban[b[i]][a[i]] = true;
    else
      match[a[i]][b[i]] = match[b[i]][a[i]] = c[i];
    g[a[i]].push_back(b[i]);
    g[b[i]].push_back(a[i]);
  }

  vector<int> path;
  vector<int> group_id(N, -1);
  vector<bool> group_begin(N, false);
  vector<bool> group_first;
  vector<bool> group_end(N, false);

  function<void(int, int)> dfs = [&](int v, int g_id) {
    group_id[v] = g_id;
    path.push_back(v);
    for (int u : g[v]) {
      if (group_id[u] == -1) dfs(u, g_id);
    }
  };

  int cycle_id_min = -1;
  {
    int k = 0;
    for (int i = 0; i < N; i++) {
      if (group_id[i] == -1 && g[i].size() == 1) {
        group_begin[i] = true;
        group_first.push_back(i);
        dfs(i, k++);
        group_end[path.back()] = true;
      }
    }
    cycle_id_min = k;
    for (int i = 0; i < N; i++) {
      if (group_id[i] == -1) {
        group_begin[i] = true;
        group_first.push_back(i);
        dfs(i, k++);
        group_end[path.back()] = true;
      }
    }
    dmp(path);
    dmp(group_id);
    dmp(group_end);
    dmp(cycle_id_min);
  }

  auto dp = vect(N + 1, vect(2, vect(2, vect(N + 1, -INF))));
  dp[0][0][0][0] = 0;
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        for (int l = 0; l <= N; l++) {
          if (dp[i][j][k][l] == -INF) continue;
          int v = path[i];
          if (group_begin[v]) {
            chmax(dp[i + 1][0][0][l], dp[i][j][k][l]);
            chmax(dp[i + 1][1][1][l + 1], dp[i][j][k][l]);
          } else if (group_end[v] && group_id[v] >= cycle_id_min) {
            chmax(dp[i + 1][j][0][l], dp[i][j][k][l]);
            int u = path[i - 1];
            int g_first = group_first[group_id[v]];
            bool ban_prev = (k == 1) && ban[u][v];
            bool ban_first = (j == 1) && ban[v][g_first];
            if (!ban_prev && !ban_first) {
              int up = 0;
              if (k == 1) up += match[u][v];
              if (j == 1) up += match[v][g_first];
              chmax(dp[i + 1][j][1][l + 1], dp[i][j][k][l] + up);
            }
          } else {
            int u = path[i - 1];
            chmax(dp[i + 1][j][0][l], dp[i][j][k][l]);
            if (k == 0 || !ban[u][v]) {
              int up = (k == 0) ? 0 : match[u][v];
              chmax(dp[i + 1][j][1][l + 1], dp[i][j][k][l] + up);
            }
          }
        }
      }
    }
  }

  int ans = -INF;
  for (int j = 0; j < 2; j++) {
    for (int k = 0; k < 2; k++) { chmax(ans, dp[N][j][k][K]); }
  }

  if (ans == -INF)
    cout << "Impossible" << endl;
  else
    cout << ans << endl;

  return;
}

int main() {
  fastio();
  if (!multitest) {
    solve();
  } else {
    cerr << "[Warning] Multi testcase mode on" << endl;
    int t;
    cin >> t;
    while (t--) solve();
  }
  return 0;
}
accuracy: 0.3488372093023256
time_ms: 40
memory_kb: 82812
final_rank: 18

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

using namespace std;

#define eps 1e-9
#define INF 2000000000              // 2e9
#define LLINF 2000000000000000000ll // 2e18 (llmax:9e18)
#define all(x) (x).begin(), (x).end()
#define sq(x) ((x) * (x))

#define rep(i, x) for (int i = 0; i < (int)(x); i++)
#define drep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)

#define popcount __builtin_popcount
#define next __next
#define prev __prev

#ifndef LOCAL
#define dmp(...) ;
#else
#define dmp(...)                                                               \
  cerr << "[ " << #__VA_ARGS__ << " ] : " << dump_str(__VA_ARGS__) << endl
#endif

// ---------------- Utility ------------------

template <class T>
bool chmin(T &a, const T &b) {
  if (a <= b) return false;
  a = b;
  return true;
}

template <class T>
bool chmax(T &a, const T &b) {
  if (a >= b) return false;
  a = b;
  return true;
}

template <class T>
using MaxHeap = priority_queue<T>;

template <class T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;

template <class T>
vector<T> vect(int len, T elem) {
  return vector<T>(len, elem);
}

// ----------------- Input -------------------

template <class T, class U>
istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}

template <class T>
istream &operator>>(istream &is, vector<T> &vec) {
  for (int i = 0; i < vec.size(); i++) is >> vec[i];
  return is;
}

// ----------------- Output ------------------

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ',' << p.second;
}

template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (const T &e : v) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const deque<T> &d) {
  for (const T &e : d) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const set<T> &s) {
  os << "{ ";
  for (const T &e : s) os << e << " ";
  return os << "}";
}

template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &m) {
  os << "{ ";
  for (const auto &[key, val] : m) os << "( " << key << " -> " << val << " ) ";
  return os << "}";
}

template <class TupleTy, size_t... I>
void dump_tuple(ostream &os, const TupleTy t, std::index_sequence<I...>) {
  (..., (os << (I == 0 ? "" : ",") << std::get<I>(t)));
}

template <class... Args>
ostream &operator<<(ostream &os, const tuple<Args...> &t) {
  os << "(";
  dump_tuple(os, t, std::make_index_sequence<sizeof...(Args)>());
  return os << ")";
}

void dump_str_rec(ostringstream &) {}

template <class Head, class... Tail>
void dump_str_rec(ostringstream &oss, Head &&head, Tail &&... tail) {
  oss << ", " << head;
  dump_str_rec(oss, forward<Tail>(tail)...);
}

template <class T, class... U>
string dump_str(T &&arg, U &&... args) {
  ostringstream oss;
  oss << arg;
  dump_str_rec(oss, forward<U>(args)...);
  return oss.str();
}

// --------------- Fast I/O ------------------

void fastio() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout << fixed << setprecision(20);
}

// ------------------ ACL --------------------

// #include <atcoder/modint>
// constexpr int MOD = 998244353;
// constexpr int MOD = 1000000007;
// using mint = atcoder::static_modint<MOD>;
// ostream &operator<<(ostream &os, const mint &v) {
//   return os << v.val();
// }

// ------------ End of template --------------

#define endl "\n"
using ll = long long;
using pii = pair<int, int>;

const bool multitest = false;

void solve() {
  int N, M, K;
  cin >> N >> M >> K;
  vector<int> a(M), b(M), c(M);
  auto match = vect(N, vect(N, 0));
  auto ban = vect(N, vect(N, false));
  vector<vector<int>> g(N);
  for (int i = 0; i < M; i++) {
    cin >> a[i] >> b[i] >> c[i];
    a[i]--;
    b[i]--;
    if (c[i] == 0)
      ban[a[i]][b[i]] = ban[b[i]][a[i]] = true;
    else
      match[a[i]][b[i]] = match[b[i]][a[i]] = c[i];
    g[a[i]].push_back(b[i]);
    g[b[i]].push_back(a[i]);
  }

  vector<int> path;
  vector<int> group_id(N, -1);
  vector<bool> group_begin(N, false);
  vector<bool> group_first;
  vector<bool> group_end(N, false);

  function<void(int, int)> dfs = [&](int v, int g_id) {
    group_id[v] = g_id;
    path.push_back(v);
    for (int u : g[v]) {
      if (group_id[u] == -1) dfs(u, g_id);
    }
  };

  int cycle_id_min = -1;
  {
    int k = 0;
    for (int i = 0; i < N; i++) {
      if (group_id[i] == -1 && g[i].size() == 1) {
        group_begin[i] = true;
        group_first.push_back(i);
        dfs(i, k++);
        group_end[path.back()] = true;
      }
    }
    cycle_id_min = k;
    for (int i = 0; i < N; i++) {
      if (group_id[i] == -1) {
        group_begin[i] = true;
        group_first.push_back(i);
        dfs(i, k++);
        group_end[path.back()] = true;
      }
    }
    dmp(path);
    dmp(group_id);
    dmp(group_end);
    dmp(cycle_id_min);
  }

  auto dp = vect(N + 1, vect(2, vect(2, vect(N + 1, -INF))));
  dp[0][0][0][0] = 0;
  for (int i = 0; i <= N; i++) {
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        for (int l = 0; l <= N; l++) {
          if (dp[i][j][k][l] == -INF) continue;
          if (i == N) continue;
          int v = path[i];
          if (group_begin[v]) {
            chmax(dp[i + 1][0][0][l], dp[i][j][k][l]);
            chmax(dp[i + 1][1][1][l + 1], dp[i][j][k][l]);
          } else if (group_end[v] && group_id[v] >= cycle_id_min) {
            chmax(dp[i + 1][j][0][l], dp[i][j][k][l]);
            int u = path[i - 1];
            int g_first = group_first[group_id[v]];
            bool ban_prev = (k == 1) && ban[u][v];
            bool ban_first = (j == 1) && ban[v][g_first];
            if (!ban_prev && !ban_first) {
              int up = 0;
              if (k == 1) up += match[u][v];
              if (j == 1) up += match[v][g_first];
              chmax(dp[i + 1][j][1][l + 1], dp[i][j][k][l] + up);
            }
          } else {
            int u = path[i - 1];
            chmax(dp[i + 1][j][0][l], dp[i][j][k][l]);
            if (k == 0 || !ban[u][v]) {
              int up = (k == 0) ? 0 : match[u][v];
              chmax(dp[i + 1][j][1][l + 1], dp[i][j][k][l] + up);
            }
          }
        }
      }
    }
  }

  int ans = -INF;
  for (int j = 0; j < 2; j++) {
    for (int k = 0; k < 2; k++) { chmax(ans, dp[N][j][k][K]); }
  }

  if (ans == -INF)
    cout << "Impossible" << endl;
  else
    cout << ans << endl;

  return;
}

int main() {
  fastio();
  if (!multitest) {
    solve();
  } else {
    cerr << "[Warning] Multi testcase mode on" << endl;
    int t;
    cin >> t;
    while (t--) solve();
  }
  return 0;
}
accuracy: 0.3488372093023256
time_ms: 50
memory_kb: 82780
final_rank: 20

code_snippet: #pragma GCC tag("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 5050000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-9;
const int mod = 1e9 + 7;
//const int mod = 998244353;

int ep[2][2][2][5050];

int main(){
    int n,m,K; cin >> n >> m >> K;
    vector<vpl> G(n);
    rep(i,m){
        int a,b,c; cin >> a >> b >> c; a--; b--;
        G[a].emplace_back(b,c);
        G[b].emplace_back(a,c);
    }
    vvl dp(2,vl(K+1,-inf));
    dp[0][0] = 0;
    vb vis(n,false);
    int dsz = 0;
    deque<int> dq;
    rep(i,n){
        if(G[i].size() == 1) dq.push_front(i);
        else dq.push_back(i);
    }
    while(!dq.empty()){
        int s = dq.front(); dq.pop_front();
        if(vis[s]) continue;
        bool one = (G[s].size() == 1);
        rep(j,K+1) dp[1][j] = -inf;
        rep(j,2) rep(k,2) rep(l,2) rep(o,K+1) ep[j][k][l][o] = -inf;
        ep[0][0][0][0] = ep[0][1][1][1] = 0;
        vis[s] = true;
        int esz = 0;
        int las = -1;
        auto dfs = [&](auto &&dfs, int u, int p) -> void {
            esz++;
            las = u;
            for(auto v : G[u]){
                if(vis[v.first]) continue;
                vis[v.first] = true;
                rep(j,2) rep(k,2) rep(l,K+1) ep[1][j][k][l] = -inf;
                rep(j,2) rep(k,2) rep(l,K+1) rep(o,2){
                    int nc = ep[0][j][k][l];
                    int nl = l+o;
                    if(nl > K) continue;
                    if(j && o){
                        if(v.second == 0) continue;
                        nc += v.second;
                    }
                    chmax(ep[1][o][k][nl], nc);
                }
                swap(ep[0],ep[1]);
                dfs(dfs,v.first,u);
            }
        };
        dfs(dfs,s,-1);
        int lc = inf;
        for(auto v : G[las]) if(v.first == s) lc = v.second;
        for(int j=dsz; j>=0; j--) for(int k=esz; k>=0; k--){
            if(j+k > K) continue;
            int C = -inf;
            rep(l,2) rep(o,2){
                if(l && o && !one){
                    if(lc == inf) chmax(C, ep[0][l][o][k]);
                    else if(lc == 0) continue;
                    else chmax(C, ep[0][l][o][k] + lc);
                }else{
                    chmax(C, ep[0][l][o][k]);
                }
            }
            chmax(dp[1][j+k], dp[0][j] + C);
        }
        dsz += esz;
        swap(dp[0],dp[1]);
    }
    int ans = dp[0][K];
    if(ans < -1e8){
        cout << "Impossible\n";
        return 0;
    }
    cout << ans << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 3916
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

long long inf = 1001001001001001001;

int main() {
    int N,M,K;
    cin >> N >> M >> K;
    vector<vector<pair<int,long long>>>road(N);
    for(int i = 0; i < M; i++) {
        int a,b,c;
        cin >> a >> b >> c;
        a--;
        b--;
        if(c == 0) {
            road[a].push_back({b,-inf});
            road[b].push_back({a,-inf});
        }
        else {
            road[a].push_back({b,c});
            road[b].push_back({a,c});
        }
    }
    vector<int>used(N);
    vector<vector<long long>>dp(N+1,vector<long long>(K+2,-inf));
    dp[0][0] = 0;
    int cnt = 0;
    for(int i = 0; i < N; i++) {
        if(road[i].size() == 0) {
            used[i] = 1;
            for(int j = 0; j <= K; j++) {
                dp[cnt+1][j] = max(dp[cnt+1][j],dp[cnt][j]);
                dp[cnt+1][j+1] = max(dp[cnt+1][j+1],dp[cnt][j]);
            }
            cnt++;
        }
        if(!used[i] && road[i].size() == 1) {
            vector<long long>tmp;
            queue<int>que;
            que.push(i);
            used[i] = 1;
            while (!que.empty()) {
                int x = que.front();
                que.pop();
                for(int j = 0; j < road[x].size(); j++) {
                    if(!used[road[x][j].first]) {
                        tmp.push_back(road[x][j].second);
                        used[road[x][j].first] = 1;
                        que.push(road[x][j].first);
                    }
                }
            }
            vector<vector<long long>>dp1(2,vector<long long>(tmp.size()+3,-inf));
            vector<vector<long long>>dp2(2,vector<long long>(tmp.size()+3,-inf));
            dp1[0][0] = dp1[1][1] = 0;
            for(int i = 0; i < tmp.size(); i++) {
                for(int j = 0; j <= tmp.size()+1; j++) {
                    dp2[0][j] = max({dp2[0][j],dp1[0][j],dp1[1][j]});
                    dp2[1][j+1] = max(dp2[1][j+1],dp1[0][j]);
                    dp2[1][j+1] = max(dp2[1][j+1],dp1[1][j]+tmp[i]);
                }
                for(int j = 0; j <= tmp.size()+1; j++) {
                    dp1[0][j] = dp2[0][j];
                    dp1[1][j] = dp2[1][j];
                    dp2[0][j] = dp2[1][j] = -inf;
                }
            }
            for(int j = 0; j <= K; j++) {
                for(int k = 0; k <= tmp.size()+1 && j+k <= K; k++) {
                    dp[cnt+tmp.size()+1][j+k] = max(dp[cnt+tmp.size()+1][j+k],dp[cnt][j]+max(dp1[0][k],dp1[1][k]));
                }
            }
            cnt += tmp.size()+1;
        }
    }
    for(int i = 0; i < N; i++) {
        if(!used[i]) {
            vector<long long>tmp;
            queue<int>que;
            que.push(i);
            used[i] = 1;
            long long a = 0;
            while (!que.empty()) {
                int x = que.front();
                que.pop();
                bool f = false;
                for(int j = 0; j < road[x].size(); j++) {
                    if(!used[road[x][j].first] && !f) {
                        tmp.push_back(road[x][j].second);
                        used[road[x][j].first] = 1;
                        que.push(road[x][j].first);
                        f = true;
                    }
                    else if(!used[road[x][j].first]) {
                        a = road[x][j].second;
                    }
                }
            }
            vector<vector<long long>>dp1(4,vector<long long>(tmp.size()+3,-inf));
            vector<vector<long long>>dp2(4,vector<long long>(tmp.size()+3,-inf));
            dp1[0][0] = dp1[3][1] = 0;
            for(int i = 0; i < tmp.size(); i++) {
                for(int j = 0; j <= tmp.size()+1; j++) {
                    for(int k = 0; k < 4; k++) {
                        dp2[0+(2&k)][j] = max(dp2[0+(2&k)][j],dp1[k][j]);
                        if(!(1&k)) {
                            dp2[1+(2&k)][j+1] = max(dp2[1+(2&k)][j+1],dp1[k][j]);
                        }
                        if(1&k) {
                            dp2[1+(2&k)][j+1] = max(dp2[1+(2&k)][j+1],dp1[k][j]+tmp[i]);
                        }
                    }
                }
                for(int j = 0; j <= tmp.size()+1; j++) {
                    for(int k = 0; k < 4; k++) {
                        dp1[k][j] = dp2[k][j];
                        dp2[k][j] = -inf;
                    }
                }
            }
            for(int j = 0; j <= K; j++) {
                for(int k = 0; k <= tmp.size()+1 && j+k <= K; k++) {
                    for(int l = 0; l < 4; l++) {
                        dp[cnt+tmp.size()+1][j+k] = max(dp[cnt+tmp.size()+1][j+k],dp[cnt][j]+dp1[l][k]+(3 == l)*a);
                    }
                }
            }
            cnt += tmp.size()+1;
        }
    }
    if(abs(dp[N][K]) > 2001001001) {
        cout << "Impossible" << endl;
    }
    else {
        cout << dp[N][K] << endl;
    }
}
accuracy: 1
time_ms: 50
memory_kb: 34804
final_rank: 10