题目意思就是让你求无向图最小环,但是给数据的方式非常恶心。
我的用并查集+暴力的方式……
先给每个边的顶点标号,然后…… 把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;
}