大意不再赘述。
思路:最直接的思路是通过暴力枚举将每一条边置为0,求一次最短路,然后再恢复,正解应该是通过Floyd算法来求解的,但我没想出来。
CODE:
#include <iostream> #include <cstdlib> #include <cstring> #include <string> #include <cstdio> #include <map> #include <queue> using namespace std; const int MAXN = 110; const int MAXM = 10010; const int INF = 0x3f3f3f3f; map<string, int> Map; struct Edge { int v, w; int next; }edge[MAXM]; int first[MAXN], d[MAXN]; char str1[MAXN], str2[MAXN]; int n, m; int cnt; int tot; void init() { cnt = 0; tot = 2; memset(first, -1, sizeof(first)); Map.clear(); } void spfa(int src) { queue<int> q; bool inq[MAXN] = {0}; for(int i = 1; i <= tot; i++) d[i] = (i == src)?0:INF; q.push(src); while(!q.empty()) { int x = q.front(); q.pop(); inq[x] = 0; for(int e = first[x]; e != -1; e = edge[e].next) { int v = edge[e].v, w = edge[e].w; if(d[v] > d[x] + w) { d[v] = d[x] + w; if(!inq[v]) { q.push(v); inq[v] = 1; } } } } } void read_graph(int u, int v, int w) { edge[cnt].v = v, edge[cnt].w = w; edge[cnt].next = first[u], first[u] = cnt++; } void read_case() { scanf("%d", &m); while(m--) { int u, v, w; scanf("%s%s%d", str1, str2, &w); if(!Map[str1]) Map[str1] = ++tot; if(!Map[str2]) Map[str2] = ++tot; u = Map[str1], v = Map[str2]; read_graph(u, v, w); read_graph(v, u, w); } } void solve() { int ans = INF; for(int u = 1; u <= tot; u++) { for(int e = first[u]; e != -1; e = edge[e].next) { int t = edge[e].w; edge[e].w = 0; spfa(1); ans = min(ans, d[2]); edge[e].w = t; } } printf("%d\n", ans); } int main() { while(~scanf("%s%s", str1, str2)) { init(); Map[str1] = 1; Map[str2] = 2; read_case(); solve(); } return 0; }