生活随笔
收集整理的這篇文章主要介紹了
Aizu 2224 Save your cats
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接
題意
貓被困在圍欄里,問最少去掉多長的邊,使所有貓逃出來。
問題轉化為將N個圖轉化為樹,因為樹不會成環,樹加上一條邊就可以成環
AC
- 并查集 + prim
對于每個圖,求它的最大生成樹,總長度減去所有的最大生成樹就是需要去掉的邊
using namespace std;
int inf =
0x3f3f3f3f;
int n, m, pre[N];
double sum;
bool vis[N];
double dis[N];
struct ac{
int v;
double c;
};
vector<P> a(N);
vector<ac> g[N];
void init() {
for (
int i =
1; i <N; ++i) {pre[i] = i;}
}
int find(
int x) {
if (x == pre[x])
return x;
else return pre[x] = find(pre[x]);
}
void join(
int x,
int y) {
int fx = find(x);
int fy = find(y);
if (fx == fy)
return;
else if (fx < fy) pre[fy] = fx;
else pre[fx] = fy;
}
void prim(
int x) {mem(dis,
0);mem(vis,
false);
for (
int i =
0; i < g[x].size(); ++i) {ac t = g[x][i];dis[t.v] = t.c;}vis[x] =
true;
for (
int i =
1; i < n; ++i) {
double MAX =
0;
int u = -
1;
for (
int j =
1; j <= n; ++j) {
if (vis[j])
continue;
if (dis[j] > MAX) {MAX = dis[j];u = j;}}
if (u == -
1)
return;vis[u] =
true;sum += MAX;
for (
int j =
0; j < g[u].size(); ++j) {ac t = g[u][j];
if (vis[t.v])
continue;
if (dis[t.v] < t.c ) {dis[t.v] = t.c;}}}
}
int main(){
ios::sync_with_stdio(
false);
while (
cin >> n >> m) {init();
for (
int i =
1; i <= n; ++i) {
cin >> a[i].first >> a[i].second;}
double ans =
0;
for (
int i =
0; i < m; ++i) {
int u, v;
cin >> u >> v;
int dx = a[u].first - a[v].first;
int dy = a[u].second - a[v].second;
double temp =
sqrt(dx * dx + dy * dy);ans += temp;g[u].push_back((ac){v, temp});g[v].push_back((ac){u, temp});join(u, v);}
for (
int i =
1; i <= n; ++i) {
if (pre[i] == i) {sum =
0;prim(i);ans -= sum;}}
printf(
"%.3lf\n",ans);
for (
int i =
1; i <= n; ++i) {g[i].clear();}}
return 0;
}
- 貪心
對所有邊降序排列,如果兩個邊不連通,就減去這條邊,剩下的就是需要去掉的邊
using namespace std;
int inf =
0x3f3f3f3f;
int n, m, pre[N];
struct ac{
int u, v;
double c;
bool operator < (
const ac &x)
const {
return c > x.c;}
};
vector<P> a(N);
vector<ac> g;
void init() {
for (
int i =
1; i <N; ++i) {pre[i] = i;}
}
int find(
int x) {
if (x == pre[x])
return x;
else return pre[x] = find(pre[x]);
}
bool join(
int x,
int y) {
int fx = find(x);
int fy = find(y);
if (fx == fy)
return false;
else if (fx < fy) pre[fy] = fx;
else pre[fx] = fy;
return true;
}
double rm() {
double sum =
0;
for (
int i =
0; i < g.size(); ++i) {ac t = g[i];
if (join(t.u, t.v)) sum += t.c;}
return sum;
}
int main(){
ios::sync_with_stdio(
false);
while (
cin >> n >> m) {init();
for (
int i =
1; i <= n; ++i) {
cin >> a[i].first >> a[i].second;}
double ans =
0;
for (
int i =
0; i < m; ++i) {
int u, v;
cin >> u >> v;
int dx = a[u].first - a[v].first;
int dy = a[u].second - a[v].second;
double temp =
sqrt(dx * dx + dy * dy);ans += temp;g.push_back((ac){u, v, temp});}sort(g.begin(), g.end());ans -= rm();
printf(
"%.3lf\n",ans);g.clear();}
return 0;
}
總結
以上是生活随笔為你收集整理的Aizu 2224 Save your cats的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。