uva 11183 Teen Girl Squad
题目大意:你有一个好消息要告诉你的n-1个朋友,不过你们不在同一个地方,因此只能靠打电话。给出m个三元组(u, v, w)表示u打电话给v要花w的钱(v不能给u打电话),你的任务是用最少的总费用把这个好消息通知到所有人。
解题思路:有向的最小生成树。最小树形图,用朱刘算法。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
const int N = 1005;
const int M = 40005;
const int INF = 0x3f3f3f3f;
typedef long long ll;
int n, m;
int Gra[N][N], cnt;
int pre[N], id[N], vis[N], in[N];
struct Edge{
int u, v, d;
}edges[M];
void init() {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
Gra[i][j] = INF;
}
}
}
void input() {
int u, v, d;
for (int i = 0; i < m; i++) {
scanf("%d %d %d", &u, &v, &d);
if (u == v) continue;
Gra[u][v] = min(Gra[u][v], d);
}
cnt = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (Gra[i][j] == INF) continue;
edges[cnt].u = i;
edges[cnt].v = j;
edges[cnt++].d = Gra[i][j];
}
}
}
int ZL(int root) {
int ans = 0, u, v;
while (1) {
for (int i = 0; i < n; i++) in[i] = INF;
for (int i = 0; i < cnt; i++) {
if (edges[i].u == edges[i].v) continue;
if (edges[i].d < in[edges[i].v]) {
pre[edges[i].v] = edges[i].u;
in[edges[i].v] = edges[i].d;
}
}
for (int i = 0; i < n; i++) {
if (i != root && in[i] == INF) return -1;
}
int tn = 0;
memset(id, -1, sizeof(id));
memset(vis, -1, sizeof(vis));
in[root] = 0;
for (int i = 0; i < n; i++) {
ans += in[i];
v = i;
while (vis[v] != i && id[v] == -1 && v != root) {
vis[v] = i;
v = pre[v];
}
if (v != root && id[v] == -1) {
for (int u = pre[v]; u != v; u = pre[u]) {
id[u] = tn;
}
id[v] = tn++;
}
}
if (tn == 0) break;
for (int i = 0; i < n; i++) {
if (id[i] == -1) id[i] = tn++;
}
for (int i = 0; i < cnt; ) {
v = edges[i].v;
edges[i].u = id[edges[i].u];
edges[i].v = id[edges[i].v];
if (edges[i].u != edges[i].v) edges[i++].d -= in[v];
else swap(edges[i], edges[--cnt]);
}
n = tn;
root = id[root];
}
return ans;
}
void solve() {
int ans = ZL(0);
if (ans == -1) printf("Possums!\n");
else printf("%d\n", ans);
}
int main() {
int T, Case = 1;
scanf("%d", &T);
while (T--) {
printf("Case #%d: ", Case++);
scanf("%d %d", &n, &m);
init();
input();
solve();
}
return 0;
}