单点度限制最小生成树存代码

来源:互联网 发布:曾仕强预言2035知乎 编辑:程序博客网 时间:2024/06/06 10:59

Problem Description

Given a weighted graph G,a specific vertex v0 and an integer K, find a spanning tree T with restriction deg(v0)=K (we don’t care about other vertices’ degrees) and minimize the weight sum of edges of T.

Algorithm

Refer to 《最小生成树问题的拓展》汪汀. Thanks to Prof. Carvalho, Lemma 1 can be proved through modeled by matchings.

Code

example:http://codeforces.com/contest/125/problem/E

#include <cstdio>#include <cstdlib>#include <algorithm>#include <utility>#include <cstring>#include <map>#include <climits>#include <queue>#include <cmath>#include <set>#include <stack>using namespace std;typedef long long LL;typedef unsigned long long ULL;typedef unsigned UI;typedef pair<int, int> PAIR;const int MAXN(5010);const int MAXE(200010);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 FS {    int fa[MAXN];    void init(int n) {        for (int i = 0; i < n; ++i) fa[i] = i;    }    int find(int u) {        if (fa[u] != u)            fa[u] = find(fa[u]);        return fa[u];    }} fs;struct E {    int u, v, ti;    E *next;    E(int u_, int v_, int w_, E *n_) :u(u_), v(v_), next(n_) {}    E(){}};int aA[MAXE / 2], bA[MAXE / 2], cA[MAXE / 2];int order[MAXE / 2];int adj[MAXN], best[MAXN], cand[MAXN];bool choose[MAXE / 2];struct G {    E *first[MAXN];    E edge[MAXE], *rear;    void init(int n) {        memset(first, 0, sizeof(first[0])*n);        rear = edge;    }    void addEdge(int u, int v, int ti) {        rear->ti = ti;      //ti存储边的索引        rear->u = u;        rear->v = v;        rear->next = first[u];        first[u] = rear++;    }    void dfs(int u, int f) {        for (E *i = first[u]; i; i = i->next) {            int ti = i->ti;            int v = i->v;            if (!choose[ti] || v == f) continue;            if (u != 0) {                best[v] = cA[ti];                cand[v] = ti;                if (checkmax(best[v], best[u]))                    cand[v] = cand[u];            }            else {                best[v] = -INF;                cand[v] = -1;            }            dfs(v, u);        }    }} g;bool cmp(int a, int b) {    return cA[a] < cA[b];}vector<int> restMST(int n, int K, vector<pair<PAIR, int> > link) { //deg(v_0)=K条件下的MST, n为点数,link为无向非环边集    int m = (int)link.size();    for (int i = 0; i < m; ++i) {        pair<PAIR, int> t = link[i];        aA[i] = t.first.first;        bA[i] = t.first.second;        cA[i] = t.second;        order[i] = i;        if (aA[i] > bA[i]) swap(aA[i], bA[i]);    }    sort(order, order + m, cmp);    fs.init(n);    for (int i = 0; i < m; ++i) {        int ti = order[i];        choose[ti] = false;        if (aA[ti] == 0) continue;        int r1 = fs.find(aA[ti]), r2 = fs.find(bA[ti]);        if (r1 == r2) continue;        fs.fa[r2] = r1;        choose[ti] = true;    }    int components = 0; //G-v_0形成的连通分量数    for (int i = 1; i < n; ++i){        adj[i] = -1;        cand[i] = -1;        if (fs.fa[i] == i)            ++components;    }    if (components > K) return vector<int>(1, -1);    int cnt = 0;    for (int i = 0; i < m; ++i) {        int ti = order[i];        if (aA[ti] != 0) continue;        adj[bA[ti]] = ti;        int r = fs.find(bA[ti]);        if (cand[r] == -1) {            cand[r] = 1;     //这里是临时借用cand表示某个连通分量是否已经和v_0相连            choose[ti] = true;            ++cnt;        }    }    if (cnt != components) return vector<int>(1, -1);    g.init(n);    for (int i = 0; i < m; ++i) {        if (!choose[i]) continue;        g.addEdge(aA[i], bA[i], i);        g.addEdge(bA[i], aA[i], i);    }    while (components < K) {        g.dfs(0, -1);        int tBest = INF, tCand;        for (int i = 1; i < n; ++i) {            int ti = adj[i];            if (ti == -1 || choose[ti]) continue;            if (checkmin(tBest, cA[ti] - best[i]))                tCand = i;        }        if (tBest == INF) return vector<int>(1, -1);        int ti = adj[tCand];        g.addEdge(aA[ti], bA[ti], ti);        g.addEdge(bA[ti], aA[ti], ti);        choose[ti] = true;        ti = cand[tCand];        choose[ti] = false;        ++components;    }    vector<int> ret;    for (int i = 0; i < m; ++i)        if (choose[i])            ret.push_back(i);    return ret;}int main() {    int n, m, K;    scanf("%d%d%d", &n, &m, &K);    vector<pair<PAIR, int> > link;    int u, v, w;    for (int i = 0; i < m; ++i) {        scanf("%d%d%d", &u, &v, &w);        --u;        --v;        if (u == v) continue;        link.push_back(make_pair(PAIR(u, v), w));    }    vector<int> ans = restMST(n, K, link);    if (ans.size() == 1 && ans[0] == -1)        printf("-1\n");    else {        printf("%d\n", ans.size());        bool pr(false);        for (int i = 0; i < ans.size(); ++i) {            if (pr) printf(" ");            pr = true;            printf("%d", ans[i]+1);        }        if(pr) printf("\n");    }    return 0;}
0 0