题目意思就是让你求无向图最小环,但是给数据的方式非常恶心。
我的用并查集+暴力的方式……
先给每个边的顶点标号,然后…… 把A能到B,B也能到A的边的点,给并为一个点……
然后floyd求最小环。
floyd最小环我自己还不是非常理解…… 但是先用着,上课再想
Executing... Test 1: TEST OK [0.005 secs, 4028 KB] Test 2: TEST OK [0.003 secs, 4028 KB] Test 3: TEST OK [0.005 secs, 4028 KB] Test 4: TEST OK [0.008 secs, 4028 KB] Test 5: TEST OK [0.005 secs, 4028 KB] Test 6: TEST OK [0.008 secs, 4028 KB] Test 7: TEST OK [0.014 secs, 4028 KB] Test 8: TEST OK [0.049 secs, 4028 KB] Test 9: TEST OK [0.041 secs, 4028 KB] All tests OK.
/* TASK:fence6 LANG:C++ */ #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <vector> using namespace std; int n; struct edge { int Length; int Q1_out, Q2_out; vector<int>q1; vector<int>q2; edge(){} edge(int _Length):Length(_Length){} }x[1000]; int Father[1000]= {0}; int g[250][250], dist[250][250]; int father_is_who(int k) { if (Father[k]) return Father[k] = father_is_who(Father[k]); else return k; } void init() { scanf("%d", &n); for (int i = 1; i <= n; ++ i) { int Num, Length, Out1, Out2; scanf("%d%d%d%d", &Num, &Length, &Out1, &Out2); x[Num] = edge(Length); for (int j = 0; j != Out1; ++ j) { int tmp; scanf("%d", &tmp); x[Num].q1.push_back(tmp); } for (int j = 0; j != Out2; ++ j) { int tmp; scanf("%d", &tmp); x[Num].q2.push_back(tmp); } } for (int i = 1; i <= n; ++ i) { x[i].Q1_out = i * 2 - 1; x[i].Q2_out = i * 2; } for (int i = 1; i <= n; ++ i) { for (int j = 0; j != x[i].q1.size(); ++ j) { //i 从out1的点出发,可以到x[i].q1[j] int will = x[i].q1[j]; for (int k = 0; k != x[will].q1.size(); ++ k) //will从out1出发到will_will { int will_will = x[will].q1[k]; if (will_will == i) { int a = father_is_who(x[i].Q1_out); int b = father_is_who(x[will].Q1_out); if (a != b) Father[a] = b; } } for (int k = 0; k != x[will].q2.size(); ++ k) //will从out1出发到will_will { int will_will = x[will].q2[k]; if (will_will == i) { int a = father_is_who(x[i].Q1_out); int b = father_is_who(x[will].Q2_out); if (a != b) Father[a] = b; } } } for (int j = 0; j != x[i].q2.size(); ++ j) { //i 从out2的点出发,可以到x[i].q1[j] int will = x[i].q2[j]; for (int k = 0; k != x[will].q1.size(); ++ k) //will从out1出发到will_will { int will_will = x[will].q1[k]; if (will_will == i) { int a = father_is_who(x[i].Q2_out); int b = father_is_who(x[will].Q1_out); if (a != b) Father[a] = b; } } for (int k = 0; k != x[will].q2.size(); ++ k) //will从out1出发到will_will { int will_will = x[will].q2[k]; if (will_will == i) { int a = father_is_who(x[i].Q2_out); int b = father_is_who(x[will].Q2_out); if (a != b) Father[a] = b; } } } } memset(g, 30, sizeof(g)); for (int i = 1; i <= n; ++ i) { int a = father_is_who(x[i].Q1_out); int b = father_is_who(x[i].Q2_out); g[a][b] = g[b][a] = x[i].Length; } for (int i = 1; i <= 2 * n; ++ i) for (int j = 1; j <= 2 * n ; ++ j) dist[i][j] = g[i][j];//cout << g[i][j] <<" "; cout<<endl; } void doit() { int ans = 0x7fffffff; for (int k = 1; k <= 2 * n; ++ k) { for (int i = 1; i != k; ++ i) for (int j = i + 1; j != k; ++ j) if (dist[i][j] + g[j][k] + g[k][i] < ans) ans = dist[i][j] + g[j][k] + g[k][i]; for (int i = 1; i <= 2 * n; ++ i) for (int j = 1; j <= 2 * n; ++ j) if (dist[i][k] + dist[k][j] < dist[i][j]) dist[i][j] = dist[i][k] + dist[k][j]; } printf("%d\n", ans); } int main() { freopen("fence6.in", "r", stdin); freopen("fence6.out", "w", stdout); init(); doit(); return 0; }