【最小樹形圖】最小樹形圖複習

來源:互聯網
上載者:User

模板題:

poj3164 Command Network

/***********************************\ * @prob: poj3164 Command Network  * * @auth: Wang Junji               * * @stat: Accepted.                * * @date: June. 25th, 2012         * * @memo: 最小樹形圖                *\***********************************/#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <string>#include <cmath>const int maxN = 110;const double INF = 1e198;double mp[maxN][maxN], x[maxN], y[maxN];bool del[maxN];int pre[maxN], root, n, m;template <typename _Tp>inline _Tp& gmax(_Tp& a, const _Tp& b){return a > b ? a : (a = b);}/* gmax */template <typename _Tp>inline _Tp& gmin(_Tp& a, const _Tp& b){return a < b ? a : (a = b);}/* gmin */template <typename _Tp>inline _Tp sqr(const _Tp& x) {return x * x;} /* sqr */inline bool connected(){    static const int SIZE = 0x3ffff;    static int q[SIZE + 1];    static bool marked[maxN];    memset(marked, 0, sizeof marked);    int f = 0, r = 0, u, v;    for (q[r++] = 0; f - r;)    for (marked[u = q[f++]] = true, f &= SIZE, v = 0; v < n; ++v)        if (mp[u][v] < INF && !marked[v]) marked[q[r++] = v] = true, r &= SIZE;    for (int i = 0; i < n; ++i)        if (!marked[i]) return false;    return true;} /* connected */inline int loop(){    pre[root = 0] = 0;    for (int i = 0; i < n; ++i)    if (!del[i] && i != root)    {        mp[i][i] = INF; pre[i] = i;        for (int j = 0; j < n; ++j)        if (!del[j] && mp[j][i] < mp[pre[i]][i])            pre[i] = j;    } /* if */    for (int i = 0; i < n; ++i) if (!del[i] && i != root)    {        static bool vis[maxN];        memset(vis, 0, sizeof vis);        int j = i;        for (; !vis[j]; j = pre[j]) vis[j] = true;        if (j == root) continue;        else return j;    } /* if */    return -1;} /* loop */inline void update(int t, double& ans){    ans += mp[pre[t]][t];    for (int i = pre[t]; i != t; i = pre[i])        ans += mp[pre[i]][i], del[i] = true;    for (int i = 0; i < n; ++i)    if (!del[i] && mp[i][t] < INF)        mp[i][t] -= mp[pre[t]][t];    for (int j = pre[t]; j != t; j = pre[j])    for (int i = 0; i < n; ++i)    if (!del[i])    {        if (mp[i][j] < INF)            gmin(mp[i][t], mp[i][j] - mp[pre[j]][j]);        if (mp[j][i] < INF) gmin(mp[t][i], mp[j][i]);    } /* for */    return;} /* update */inline double solve(){    memset(del, 0, sizeof del);    double ans = 0; int j;    while (~(j = loop())) update(j, ans);    for (int i = 0; i < n; ++i)    if (!del[i] && i != root)        ans += mp[pre[i]][i];    return ans;} /* solve */int main(){    freopen("network.in" , "r", stdin );    freopen("network.out", "w", stdout);    while (~scanf("%d%d", &n, &m))    {        for (int i = 0; i < n; ++i)        for (int j = 0; j < n; ++j)            mp[i][j] = INF;        for (int i = 0; i < n; ++i)            scanf("%lf%lf", x + i, y + i);        while (m--)        {            int u, v; scanf("%d%d", &u, &v); --u, --v;            mp[u][v] = sqrt(sqr(x[u] - x[v]) + sqr(y[u] - y[v]));        } /* while */        if (!connected()) puts("poor snoopy");        else printf("%.2lf\n", solve());    } /* while */    return 0;} /* main *//*最小樹形圖模板題,不多說。*/

tju2248 Channel Design

/**********************************\ * @prob: tju2248 Channel Design  * * @auth: Wang Junji              * * @stat: Accepted.               * * @date: June. 25th, 2012        * * @memo: 最小樹形圖                *\**********************************/#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <string>const int maxN = 110, maxM = 10010, INF = 0x3f3f3f3f;struct Edge{    int u, v, d;    Edge(int u = 0, int v = 0, int d = 0): u(u), v(v), d(d) {} /* Edge */} edge[maxM];int n, m;int Directed_MST(int root, int n, int m){    int res = 0;    for (;;)    {        static int In[maxN], pre[maxN], ID[maxN], vis[maxN];        memset(In, 0x3f, sizeof In);        for (int j = 0; j < m; ++j)        {            int u = edge[j].u, v = edge[j].v, d = edge[j].d;            if (u != v && d < In[v]) In[v] = d, pre[v] = u;        } /* for */        for (int i = 0; i < n; ++i)        if (i != root && In[i] == INF)            return -1;        memset(vis, 0xff, sizeof vis);        memset(ID , 0xff, sizeof ID );        int cnt_v = 0;        for (int i = 0; i < n; ++i) if (i != root)        {            res += In[i]; int u = i;            for (; vis[u] != i && ID[u] == -1 && u != root; u = pre[u])                vis[u] = i;            if (u != root && ID[u] == -1)            {                for (int v = pre[u]; v != u; v = pre[v])                    ID[v] = cnt_v;                ID[u] = cnt_v++;            } /* if */        } /* if */        if (!cnt_v) break;        for (int i = 0; i < n; ++i) if (ID[i] == -1) ID[i] = cnt_v++;        for (int j = 0; j < m; ++j)        {            int v = edge[j].v;            edge[j].u = ID[edge[j].u];            edge[j].v = ID[edge[j].v];            if (edge[j].u != edge[j].v)                edge[j].d -= In[v];        } /* for */        n = cnt_v;        root = ID[root];    } /* for */    return res;} /* Directed_MST */int main(){    freopen("design.in" , "r", stdin );    freopen("design.out", "w", stdout);    while (~scanf("%d%d", &n, &m) && (n || m))    {        int cnt_e = 0;        while (m--)        {            int u, v, d; scanf("%d%d%d", &u, &v, &d);            edge[cnt_e++] = Edge(--u, --v, d);        } /* while */        int ans = Directed_MST(0, n, cnt_e);        if (ans < 0) puts("impossible");        else printf("%d\n", ans);    } /* while */    return 0;} /* main *//*最小樹形圖模板題,不多說。*/

UVa11183 Teen Girl Squad

/************************************\ * @prob: UVa11183 Teen Girl Squad  * * @auth: Wang Junji                * * @stat: Accepted.                 * * @date: June. 25th, 2012          * * @memo: 最小樹形圖                 *\************************************/#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <string>const int maxN = 1010, maxM = 40010, INF = 0x3f3f3f3f;struct Edge {int u, v, d;} edge[maxM];int n, m, T;int Directed_MST(int root, int n, int m){    int res = 0;    for (;;)    {        static int In[maxN], pre[maxN], ID[maxN], vis[maxN];        memset(In, 0x3f, sizeof In);        for (int j = 0; j < m; ++j)        {            int u = edge[j].u, v = edge[j].v, d = edge[j].d;            if (u != v && d < In[v]) In[v] = d, pre[v] = u;        } /* for */        for (int i = 0; i < n; ++i)        if (i != root && In[i] == INF)            return -1;        memset(ID , 0xff, sizeof ID );        memset(vis, 0xff, sizeof vis);        int cnt_v = 0;        for (int i = 0; i < n; ++i) if (i != root)        {            res += In[i]; int u = i;            for (; vis[u] != i && ID[u] == -1 && u != root; u = pre[u])                vis[u] = i;            if (ID[u] == -1 && u != root)            {                for (int v = pre[u]; v != u; v = pre[v])                    ID[v] = cnt_v;                ID[u] = cnt_v++;            } /* if */        } /* if */        if (!cnt_v) break;        for (int i = 0; i < n; ++i) if (ID[i] == -1) ID[i] = cnt_v++;        for (int j = 0; j < m; ++j)        {            int v = edge[j].v;            if ((edge[j].u = ID[edge[j].u]) != (edge[j].v = ID[edge[j].v]))                edge[j].d -= In[v];        } /* for */        root = ID[root];        n = cnt_v;    } /* for */    return res;} /* Directed_MST */int main(){    freopen("girl.in" , "r", stdin );    freopen("girl.out", "w", stdout);    for (scanf("%d", &T); T--;)    {        scanf("%d%d", &n, &m);        for (int i = 0; i < m; ++i)            scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].d);        static int Case = 0;        printf("Case #%d: ", ++Case);        int ans = Directed_MST(0, n, m);        if (ans < 0) puts("Possums!");        else printf("%d\n", ans);    } /* for */    return 0;} /* main *//*最小樹形圖模板題,不多說。*/

無定根:

hdu2121 Ice_cream’s world II

/****************************************\ * @prob: hdu2121 Ice_cream’s world II  * * @auth: Wang Junji                    * * @stat: Accepted.                     * * @date: June. 25th, 2012              * * @memo: 最小樹形圖                     *\****************************************/#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <string>const int maxN = 1010, maxM = 11010;typedef long long int64;int64 INF = 0x3f3f3f3f3f3f3f3fLL;struct Edge {int u, v; int64 d;} edge[maxM];int n, m;int64 Directed_MST(int root, int n, int m, int& root_id){    int64 res = 0;    for (;;)    {        static int pre[maxN], ID[maxN], vis[maxN];        static int64 In[maxN];        memset(In, 0x3f, sizeof In);        for (int j = 0; j < m; ++j)        {            int u = edge[j].u, v = edge[j].v;            int64 d = edge[j].d;            if (u != v && d < In[v]) //!!            {                In[v] = d, pre[v] = u;                if (u == root) root_id = j;            } /* if */        } /* for */        for (int i = 0; i < n; ++i)        if (i != root && In[i] == INF)            return -1;        memset(ID , 0xff, sizeof ID );        memset(vis, 0xff, sizeof vis);        int cnt_v = 0;        for (int i = 0; i < n; ++i) if (i != root)        {            res += In[i]; int u = i;            for (; vis[u] != i && ID[u] == -1 && u != root; u = pre[u])                vis[u] = i;            if (ID[u] == -1 && u != root)            {                for (int v = pre[u]; v != u; v = pre[v])                    ID[v] = cnt_v;                ID[u] = cnt_v++;            } /* if */        } /* if */        if (!cnt_v) break;        for (int i = 0; i < n; ++i) if (ID[i] == -1) ID[i] = cnt_v++;        for (int j = 0; j < m; ++j)        {            int v = edge[j].v;            if ((edge[j].u = ID[edge[j].u]) != (edge[j].v = ID[edge[j].v]))                edge[j].d -= In[v];        } /* for */        root = ID[root]; n = cnt_v;    } /* for */    return res;} /* Directed_MST */int main(){    freopen("Ice_cream.in" , "r", stdin );    freopen("Ice_cream.out", "w", stdout);    while (~scanf("%d%d", &n, &m))    {        int64 sum_d = 0;        for (int i = 0; i < m; ++i)            scanf("%d%d%lld", &edge[i].u, &edge[i].v, &edge[i].d), sum_d += edge[i].d;        ++sum_d;        int cnt_e = m, root_id = 0;        for (int i = 0; i < n; ++i)            edge[cnt_e].u = n, edge[cnt_e].v = i, edge[cnt_e++].d = sum_d;        int64 ans = Directed_MST(n, n + 1, cnt_e, root_id) - sum_d;        if (ans < 0 || ans >= sum_d) puts("impossible\n");        else printf("%lld %d\n\n", ans, root_id - m);    } /* while */    return 0;} /* main *//*無定根的最小樹形圖。只需要加一個虛擬根,到所有點的權值恰好比所有原邊權值之和略大(這樣保證虛擬根只會與其中一個點連邊),並且再記錄一下根的位置就可以了(如果一個點的入邊為虛擬根,那麼這個點為“真實的”根)。要用long long類型。*/

(這並不是一道真正意義上的最小樹形圖:)

hdu3072 Intelligence System

/***************************************\ * @prob: hdu3072 Intelligence System  * * @auth: Wang Junji                   * * @stat: Accepted.                    * * @date: June. 25th, 2012             * * @memo: 強連通分量                    *\***************************************/#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <string>typedef long long int64;const int maxN = 50010, maxM = 100010;const int64 INF = 0x3f3f3f3f3f3f3f3fLL;struct Edge{    int u, v; int64 d; Edge* next; Edge() {} /* Edge */    Edge(int u, int v, int64 d, Edge* next):        u(u), v(v), d(d), next(next) {}    /* Edge */} __edge[maxM], *edge[maxN], *tot = __edge; bool marked[maxN];int Low[maxN], DFN[maxN], sta[maxN];int ID[maxN], n, m, Bcnt, Index, top;template <typename _Tp>inline _Tp& gmax(_Tp& a, const _Tp& b){return a > b ? a : (a = b);}/* gmax */template <typename _Tp>inline _Tp& gmin(_Tp& a, const _Tp& b){return a < b ? a : (a = b);}/* gmin */void Tarjan(int u){    DFN[u] = Low[u] = Index++;    marked[sta[top++] = u] = true;    for (Edge* p = edge[u]; p; p = p -> next)    {        if (DFN[p -> v] == -1) Tarjan(p -> v), gmin(Low[u], Low[p -> v]);        else if (marked[p -> v])               gmin(Low[u], DFN[p -> v]);    } /* for */    if (Low[u] == DFN[u])    {        int tmp = u;        do            ID[tmp = sta[--top]] = Bcnt, marked[tmp] = false;        while (tmp != u);        ++Bcnt;    } /* if */    return;} /* Tarjan */int main(){    freopen("Intelligence.in" , "r", stdin );    freopen("Intelligence.out", "w", stdout);    while (~scanf("%d%d", &n, &m))    {        memset(edge, 0, sizeof edge); tot = __edge;        while (m--)        {            int u, v; int64 d;            scanf("%d%d%lld", &u, &v, &d);            edge[u] = new (tot++) Edge(u, v, d, edge[u]);        } /* while */        memset(ID    , 0xff, sizeof ID    );        memset(DFN   , 0xff, sizeof DFN   );        memset(Low   , 0xff, sizeof Low   );        memset(marked, 0   , sizeof marked);        Bcnt = top = Index = 0;        Tarjan(0);        static int64 In[maxN];        memset(In, 0x3f, sizeof In);        for (Edge* p = __edge; p != tot; ++p)        if (ID[p -> u] != ID[p -> v])            gmin(In[ID[p -> v]], p -> d);        In[ID[0]] = 0;        int64 ans = 0;        for (int i = 0; i < Bcnt; ++i) ans += In[i];        printf("%lld\n", ans);    } /* while */    return 0;} /* main *//*縮點,然後將所有最小入邊相加。*/

稍加變形:

hdu4009 Transfer water

/**********************************\ * @prob: hdu4009 Transfer water  * * @auth: Wang Junji              * * @stat: Accepted.               * * @date: June. 25th, 2012        * * @memo: 最小樹形圖               *\**********************************/#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <string>const int maxN = 1010, maxM = maxN * (maxN + 1), INF = 0x3f3f3f3f;struct Edge {int u, v, d;} edge[maxM];int x[maxN], y[maxN], z[maxN], n, m, X, Y, Z, cnt_e;inline int dist(int i, int j){return std::abs(x[i] - x[j]) + std::abs(y[i] - y[j]) + std::abs(z[i] - z[j]);}inline void Ins(int u, int v, int d){    edge[cnt_e].u = u;    edge[cnt_e].v = v;    edge[cnt_e].d = d;    ++cnt_e; return;} /* Ins */int Directed_MST(int root, int n, int m){    int res = 0;    for (;;)    {        static int pre[maxN], ID[maxN], vis[maxN];        static int In[maxN];        memset(In, 0x3f, sizeof In);        for (int j = 0; j < m; ++j)        {            int u = edge[j].u, v = edge[j].v;            int d = edge[j].d;            if (u != v && d < In[v]) In[v] = d, pre[v] = u;        } /* for */        for (int i = 0; i < n; ++i)        if (i != root && In[i] == INF)            return -1;        memset(ID , 0xff, sizeof ID );        memset(vis, 0xff, sizeof vis);        int cnt_v = 0;        for (int i = 0; i < n; ++i) if (i != root)        {            res += In[i]; int u = i;            for (; ID[u] == -1 && u != root && vis[u] != i; u = pre[u])                vis[u] = i;            if (u != root && ID[u] == -1) //!!            {                for (int v = pre[u]; v != u; v = pre[v])                    ID[v] = cnt_v;                ID[u] = cnt_v++;            } /* if */        } /* if */        if (!cnt_v) break;        for (int i = 0; i < n; ++i) if (ID[i] == -1) ID[i] = cnt_v++; //!!        for (int j = 0; j < m; ++j)        {            int v = edge[j].v;            if ((edge[j].u = ID[edge[j].u]) != (edge[j].v = ID[edge[j].v]))                edge[j].d -= In[v];        } /* for */        n = cnt_v;        root = ID[root];    } /* for */    return res;} /* Directed_MST */int main(){    freopen("Transfer.in" , "r", stdin );    freopen("Transfer.out", "w", stdout);    while (~scanf("%d%d%d%d", &n, &X, &Y, &Z) && (n || X || Y || Z))    {        for (int i = 0; i < n; ++i)            scanf("%d%d%d", x + i, y + i, z + i);        cnt_e = 0;        for (int i = 0, K, j; i < n; ++i)        {            scanf("%d", &K);            while (K--)            {                scanf("%d", &j); --j;                Ins(i, j, Y * dist(i, j) + (z[i] < z[j] ? Z : 0));            } /* while */        } /* for */        for (int i = 0; i < n; ++i) Ins(n, i, z[i] * X);        int ans = Directed_MST(n, n + 1, cnt_e);        if (ans < 0) puts("poor XiaoA");        else printf("%d\n", ans);    } /* while */    return 0;} /* main *//*建立虛擬根,虛擬根到每個點的權值為該點自建水庫的費用。注意當i的海拔低於j時,仍然要算上Y的基本費用(Z為附加費用,而不是全部費用)。*/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.