您的位置:首页

UVA - 10462 Is There A Second Way Left?(次小生成树)

2017-08-20 12:28 507 查看
题目大意:给出一张图,看能形成几个生成树

解题思路:先推断是否能形成生成树,在推断是否有次小生成树

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

#define N 110
#define M 410
#define INF 0x3f3f3f3f

struct Edge{
int from, to, cost, next;
}E[M];
int head
, d
, maxcost

, id[M], f
;
int tot, n, m;
bool mark
, vis[M];

void AddEdge(int u, int v, int c) {
E[tot].from = u; E[tot].to = v; E[tot].cost = c; E[tot].next = head[u]; head[u] = tot++;
u = u ^ v; v = u ^ v; u = u ^ v;
E[tot].from = u; E[tot].to = v; E[tot].cost = c; E[tot].next = head[u]; head[u] = tot++;
}

void init() {
memset(head, -1, sizeof(head));
tot = 0;

scanf("%d%d", &n, &m);
int u, v, c;
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &u, &v, &c);
AddEdge(u, v, c);
}
}

int Prim() {
for (int i = 1; i <= n; i++)
d[i] = INF;
memset(vis, 0, sizeof(vis));
memset(mark, 0, sizeof(mark));
d[1] = 0;
f[1] = 1;
vector<int> v;
int ans = 0;
for (int i = 1; i <= n; i++) {
int t = INF, x;
for (int j = 1; j <= n; j++)
if (!mark[j] && d[j] < t)
t = d[x = j];
if (t == INF) {
return -1;
}

mark[x] = true;
if (x != 1) {
vis[id[x]] = vis[id[x] ^ 1] = true;
ans += E[id[x]].cost;
}
int size = v.size();
for (int j = 0; j < size; j++)
maxcost[v[j]][x] = maxcost[x][v[j]] = max(maxcost[v[j]][f[x]], E[id[x]].cost);
v.push_back(x);

for (int j = head[x]; ~j; j = E[j].next) {
int v = E[j].to;
if (!mark[v] && E[j].cost < d[v]) {
d[v] = E[j].cost;
id[v] = j;
f[v] = x;
}
}
}
return ans;
}

int cas = 1;
void solve() {
printf("Case #%d : ", cas++);
int ans = Prim();
if (ans == -1) {
printf("No way\n");
return ;
}

bool flag = false;
int ans2 = INF, u, v;
for (int i = 0; i < tot; i += 2) {
if (!vis[i]) {
u = E[i].from;
v = E[i].to;
ans2 = min(ans2, ans - maxcost[u][v] + E[i].cost);
}
}
if (ans2 == INF)
printf("No second way\n");
else
printf("%d\n", ans2);

}

int main() {
int test;
scanf("%d", &test);
while (test--) {
init();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: