Given a weighted digraph G ,a specific vertex v0 . Find an arborescence T with root v0 and minimize the weight sum of arcs of T .
https://en.wikipedia.org/wiki/Edmonds%27_algorithm
http://www.utdallas.edu/~dzdu/cs6363/read-after12.pdf
http://wenku.baidu.com/view/c0d1c09631b765ce040814aa
Example:http://poj.org/problem?id=3164
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned UI;
typedef pair<int, int> PAIR;
const int MAXN(110);
const int MAXE(11000);
const int MAXK(100010);
const int MAXL(10);
const int MAXC(2);
const int INF((INT_MAX - 1) / 2);
const int F(0);
template<typename T>
inline bool checkmax(T &a, const T &b) {
return b > a ? ((a = b), true) : false;
}
template<typename T>
inline bool checkmin(T &a, const T &b) {
return b < a ? ((a = b), true) : false;
}
template<typename T>
inline T ABS(T a) {
return a < 0 ? -a : a;
}
double dis(double x1, double y1, double x2, double y2) {
return sqrt((y2 - y1)*(y2 - y1) + (x2 - x1)*(x2 - x1));
}
double dis2(double x1, double y1, double x2, double y2) {
return (y2 - y1)*(y2 - y1) + (x2 - x1)*(x2 - x1);
}
struct E {
int u, v;
double w;
E(int u_, int v_, double w_) :u(u_), v(v_), w(w_) {}
E() {}
friend bool operator <(const E &a, const E &b) {
return a.w == b.w ? (a.u == b.u ? a.v < b.v : a.u < b.u) : a.w < b.w;
}
};
int pre[MAXN], vis[MAXN], myHash[MAXN];
double inW[MAXN];
double DMST(int n, int rt, int en, E *e) { //非负权图最小树形图;可以处理解不存在情况,平行边,自环,和指向rt的边;但为了效率考虑,最好提前处理掉这些
double ret = 0;
while (true) {
for (int i = 0; i < n; ++i) pre[i] = -1;
for (int i = 0; i < en; ++i) {
if (e[i].u == e[i].v || e[i].v == rt) continue;
int v = e[i].v;
if (pre[v] == -1 || e[i].w < inW[v]) {
pre[v] = e[i].u;
inW[v] = e[i].w;
}
}
for (int i = 0; i < n; ++i) {
vis[i] = -1;
myHash[i] = -1;
if (pre[i] == -1 && i != rt) return -1;
}
int cnt = 0;
for (int i = 0; i < n; ++i) {
if (i == rt) continue;
ret += inW[i];
if (vis[i] != -1) continue;
int u = i;
while (u != rt && vis[u] == -1) {
vis[u] = i;
u = pre[u];
}
if(u != rt && vis[u] == i) { //形成了一个圈
int t = u;
do {
myHash[u] = cnt;
u = pre[u];
} while (u != t);
++cnt;
}
}
if (cnt == 0) return ret;
for (int i = 0; i < n; ++i) {
if (myHash[i] != -1) continue;
myHash[i] = cnt++;
}
for (int i = 0; i < en; ++i) {
// if(e[i].v == rt) continue; 不要加
e[i].w -= inW[e[i].v];
e[i].u = myHash[e[i].u];
e[i].v = myHash[e[i].v];
}
rt = myHash[rt];
n = cnt;
}
}
E edge[MAXE];
double dat[MAXN][2];
int en;
int main() {
int n, m;
while (~scanf("%d%d", &n, &m)) {
for (int i = 0; i < n; ++i)
scanf("%lf%lf", dat[i], dat[i] + 1);
en = 0;
int u, v;
for (int i = 0; i < m; ++i) {
scanf("%d%d", &u, &v);
--u;
--v;
edge[en++] = E(u, v, dis(dat[u][0], dat[u][1], dat[v][0], dat[v][1]));
}
double temp = DMST(n, 0, en, edge);
if (temp < -0.5)
printf("poor snoopy\n");
else
printf("%.2f\n", temp);
}
return 0;
}
由于频繁的寻址,速度反而会下降
Example:http://acm.hdu.edu.cn/showproblem.php?pid=4009
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned UI;
typedef pair<int, int> PAIR;
const int MAXN(1010);
const int MAXE(1100000);
const int MAXK(100010);
const int MAXL(10);
const int MAXC(2);
const int INF((INT_MAX - 1) / 2);
const int F(0);
template<typename T>
inline bool checkmax(T &a, const T &b) {
return b > a ? ((a = b), true) : false;
}
template<typename T>
inline bool checkmin(T &a, const T &b) {
return b < a ? ((a = b), true) : false;
}
template<typename T>
inline T ABS(T a) {
return a < 0 ? -a : a;
}
double dis(double x1, double y1, double x2, double y2) {
return sqrt((y2 - y1)*(y2 - y1) + (x2 - x1)*(x2 - x1));
}
double dis2(double x1, double y1, double x2, double y2) {
return (y2 - y1)*(y2 - y1) + (x2 - x1)*(x2 - x1);
}
struct E {
int u, v;
int w;
E *next;
E(int u_, int v_, int w_) :u(u_), v(v_), w(w_) {}
E() {}
friend bool operator <(const E &a, const E &b) {
return a.w == b.w ? (a.u == b.u ? a.v < b.v : a.u < b.u) : a.w < b.w;
}
};
struct myList {
E ele[MAXE], head, *re, *h;
void init() {
h = &head;
h->next = 0;
re = ele;
}
void add(int u, int v, int w) {
*re = E(u, v, w);
re->next = h->next;
h->next = re++;
}
} e;
int pre[MAXN], vis[MAXN], myHash[MAXN];
double inW[MAXN];
LL DMST(int n, int rt) { //非负权图最小树形图;可以处理解不存在情况,平行边,自环,和指向rt的边;但为了效率考虑,最好提前处理掉这些
LL ret = 0;
while (true) {
for (int i = 0; i < n; ++i) pre[i] = -1;
for (E *i = e.h->next; i; i = i->next) {
int u = i->u, v = i->v, w = i->w;
if (pre[v] == -1 || w < inW[v]) {
pre[v] = u;
inW[v] = w;
}
}
for (int i = 0; i < n; ++i) {
vis[i] = -1;
myHash[i] = -1;
if (pre[i] == -1 && i != rt) return -1;
}
int cnt = 0;
for (int i = 0; i < n; ++i) {
if (i == rt) continue;
ret += inW[i];
if (vis[i] != -1) continue;
int u = i;
while (u != rt && vis[u] == -1) {
vis[u] = i;
u = pre[u];
}
if(u != rt && vis[u] == i) { //形成了一个圈
int t = u;
do {
myHash[u] = cnt;
u = pre[u];
} while (u != t);
++cnt;
}
}
if (cnt == 0) return ret;
for (int i = 0; i < n; ++i) {
if (myHash[i] != -1) continue;
myHash[i] = cnt++;
}
for (E *pi = e.h, *i = e.h->next; i; i = i->next) {
i->w -= inW[i->v];
i->u = myHash[i->u];
i->v = myHash[i->v];
if (i->u == i->v)
pi->next = i->next;
else
pi = i;
}
rt = myHash[rt];
n = cnt;
}
}
int dat[MAXN][3];
int L1Dis(int a, int b) {
int ret = 0;
for (int i = 0; i < 3; ++i) ret += ABS(dat[a][i] - dat[b][i]);
return ret;
}
int main() {
int n, X, Y, Z;
while (scanf("%d%d%d%d", &n, &X, &Y, &Z), n) {
for (int i = 1; i <= n; ++i)
scanf("%d%d%d", dat[i], dat[i] + 1, dat[i] + 2);
e.init();
for (int i = 1; i <= n; ++i) {
e.add(0, i, X*dat[i][2]);
int K, t;
scanf("%d", &K);
for (int j = 0; j < K; ++j) {
scanf("%d", &t);
if (i == t) continue;
int w = Y*L1Dis(i, t);
if (dat[i][2] < dat[t][2]) w += Z;
e.add(i, t, w);
}
}
printf("%I64d\n", DMST(n+1, 0));
}
return 0;
}