思路:有n个城市,m条单向道路,开始你在k号城市,现在要你从k开始出发,访问每个城市至少一次,就最少的花费,不行的话就impossible,这样看的话就是搜索了,,,但是题目中还给出了条件的,,,如果x号城市你之前访问过了的,那么你可以从你现在所在城市不花时间的瞬移到x号城市去。这样一来就不再是简单的搜索了,而是最小树形图了。
// #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <climits> using namespace std; // #define DEBUG #ifdef DEBUG #define debug(...) printf( __VA_ARGS__ ) #else #define debug(...) #endif #define CLR(x) memset(x, 0,sizeof x) #define MEM(x,y) memset(x, y,sizeof x) #define pk push_back template<class T> inline T Get_Max(const T&a,const T&b){return a < b?b:a;} template<class T> inline T Get_Min(const T&a,const T&b){return a < b?a:b;} typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; const double eps = 1e-10; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int maxn = 1010; int in[maxn]; struct Edge{ int u, v, w; }E[maxn << 4]; int pre[maxn], cnt, id[maxn], vis[maxn]; int root; int n, m, k; int solve(){ int sum = 0; while(true){ memset(in, INF,sizeof in); memset(pre, -1,sizeof pre); for (int i = 0;i < cnt;++i){ int u = E[i].u, v = E[i].v; if (E[i].w < in[v] && u != v){ pre[v] = u; in[v] = E[i].w; } } for (int i = 0;i < n;++i){ if (i == root) continue; if (in[i] == INF) return -1; } int Num = 0; memset(id, -1,sizeof id); memset(vis, -1,sizeof vis); in[root] = 0; for (int i = 0;i < n;++i){ sum += in[i]; int v = i; while(vis[v] != i && id[v] == -1 && v != root){ vis[v] = i; v = pre[v]; } if (v != root && id[v] == -1){ for (int u = pre[v];u != v;u = pre[u]){ id[u] = Num; } id[v] = Num++; } } if (Num == 0) break; for (int i = 0;i < n;++i) if (id[i] == -1) id[i] = Num++; for (int i = 0;i < cnt;++i){ int v = E[i].v; E[i].u = id[E[i].u]; E[i].v = id[E[i].v]; if (E[i].u != E[i].v) E[i].w = E[i].w - in[v]; } n = Num; root = id[root]; } return sum; } int main() { // ios::sync_with_stdio(false); // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int t, icase = 0; scanf("%d",&t); while(t--){ scanf("%d%d%d",&n,&m,&k); cnt = 0; int u, v, c; while(m--){ scanf("%d%d%d",&u,&v,&c); E[cnt].u = u;E[cnt].v = v;E[cnt].w = c; cnt++; } root = k; int ans = solve(); if (ans == -1) printf("Case %d: impossible\n", ++icase); else printf("Case %d: %d\n", ++icase, ans); } return 0; }