zoukankan      html  css  js  c++  java
  • 最小树形图

    最小树形图

    https://loj.ac/problem/140

    题目描述

    这是一道模板题。

    给定包含 n 个结点, m 条有向边的一个图。试求一棵以结点 r 为根的最小树形图,并输出最小树形图每条边的权值之和,如果没有以 r为根的最小树形图,输出 1。

    输入格式

    第一行包含三个整数 n,m,r,意义同题目所述。

    接下来 mm 行,每行包含三个整数 u,v,w表示图中存在一条从 u 指向 v 的权值为 w 的有向边。

    输出格式

    如果原图中存在以 r 为根的最小树形图,就输出最小树形图每条边的权值之和,否则输出 -1

    样例

    样例输入1

    4 6 1
    1 2 3
    1 3 1
    4 1 2
    4 2 2
    3 2 1
    3 4 1

    样例输出 1

    3

    样例解释 1

    最小树形图中包含第 2, 5, 6 三条边,总权值为 1 + 1 + 1 = 3

    样例输入 2

    4 6 3
    1 2 3
    1 3 1
    4 1 2
    4 2 2
    3 2 1
    3 4 1

    样例输出 2

    4

    样例输出 2

    最小树形图中包含第 3, 5, 6 三条边,总权值为 2 + 1 + 1 =4

    样例输入 3

    4 6 2
    1 2 3
    1 3 1
    4 1 2
    4 2 2
    3 2 1
    3 4 1

    样例输出 3

    -1

    样例解释 3

    无法构成最小树形图,故输出 -1 。

    模板题 

    下标从0开始

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <math.h>
     5 const int INF=0x3f3f3f3f;
     6 #define MAXN 400005
     7 #define MAXM 400010
     8 using namespace std;
     9 struct Edge{
    10     int u,v;
    11     int cost;
    12 }edge[MAXM];
    13 
    14 int pre[MAXN],id[MAXN],visit[MAXN];
    15 int in[MAXN];
    16 
    17 int zhuliu(int root,int n,int m){
    18     int res=0;
    19     while(1){
    20         for(int i=0;i<n;i++){
    21             in[i]=INF;
    22         }
    23         for(int i=0;i<m;i++){
    24             if(edge[i].u!=edge[i].v&&edge[i].cost<in[edge[i].v]){
    25                 pre[edge[i].v]=edge[i].u;
    26                 in[edge[i].v]=edge[i].cost;
    27             }
    28         }
    29         for(int i=0;i<n;i++){
    30             if(i!=root && in[i]==INF){
    31                 return -1;
    32             }
    33         }
    34         int tn=0;
    35         memset(id,-1,sizeof(id));
    36         memset(visit,-1,sizeof(visit));
    37         in[root]=0;
    38         for(int i=0;i<n;i++){
    39             res+=in[i];
    40             int v=i;
    41             while(visit[v]!=i&&id[v]==-1&&v!=root){
    42                 visit[v]=i;
    43                 v=pre[v];
    44             }
    45             if(v!=root&&id[v]==-1){
    46                 for(int u=pre[v];u!=v;u=pre[u]){
    47                     id[u]=tn;
    48                 }
    49                 id[v]=tn++;
    50             }
    51         }
    52         if(tn==0) break;
    53         for(int i=0;i<n;i++){
    54             if(id[i]==-1){
    55                 id[i]=tn++;
    56             }
    57         }
    58         for(int i=0;i<m;){
    59             int v=edge[i].v;
    60             edge[i].u=id[edge[i].u];
    61             edge[i].v=id[edge[i].v];
    62             if(edge[i].u != edge[i].v){
    63                 edge[i++].cost-=in[v];
    64             }
    65             else{
    66                 swap(edge[i],edge[--m]);
    67             }
    68         }
    69         n=tn;
    70         root=id[root];
    71     }
    72     return res;
    73 }
    74 
    75 
    76 int main(){
    77     std::ios::sync_with_stdio(false);
    78     int n,m,r;
    79     cin>>n>>m>>r;
    80     for(int i=0;i<m;i++){
    81         cin>>edge[i].u>>edge[i].v>>edge[i].cost;
    82         edge[i].u--;
    83         edge[i].v--;
    84     }
    85     int ans=zhuliu(r-1,n,m);
    86     cout<<ans<<endl;
    87 }
    View Code

    下标从1开始(要改两个地方:1.tn  2.--m -> m--)

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <math.h>
     5 const int INF=0x3f3f3f3f;
     6 #define MAXN 400005
     7 #define MAXM 400010
     8 using namespace std;
     9 struct Edge{
    10     int u,v;
    11     int cost;
    12 }edge[MAXM];
    13 
    14 int pre[MAXN],id[MAXN],visit[MAXN];
    15 int in[MAXN];
    16 
    17 int zhuliu(int root,int n,int m){
    18     int res=0;
    19     while(1){
    20         for(int i=1;i<=n;i++){
    21             in[i]=INF;
    22         }
    23         for(int i=1;i<=m;i++){
    24             if(edge[i].u!=edge[i].v&&edge[i].cost<in[edge[i].v]){
    25                 pre[edge[i].v]=edge[i].u;
    26                 in[edge[i].v]=edge[i].cost;
    27             }
    28         }
    29         for(int i=1;i<=n;i++){
    30             if(i!=root && in[i]==INF){
    31                 return -1;
    32             }
    33         }
    34         int tn=1;
    35         memset(id,-1,sizeof(id));
    36         memset(visit,-1,sizeof(visit));
    37         in[root]=0;
    38         for(int i=1;i<=n;i++){
    39             res+=in[i];
    40             int v=i;
    41             while(visit[v]!=i&&id[v]==-1&&v!=root){
    42                 visit[v]=i;
    43                 v=pre[v];
    44             }
    45             if(v!=root&&id[v]==-1){
    46                 for(int u=pre[v];u!=v;u=pre[u]){
    47                     id[u]=tn;
    48                 }
    49                 id[v]=tn++;
    50             }
    51         }
    52         if(tn==1) break;
    53         for(int i=1;i<=n;i++){
    54             if(id[i]==-1){
    55                 id[i]=tn++;
    56             }
    57         }
    58         for(int i=1;i<=m;){
    59             int v=edge[i].v;
    60             edge[i].u=id[edge[i].u];
    61             edge[i].v=id[edge[i].v];
    62             if(edge[i].u != edge[i].v){
    63                 edge[i++].cost-=in[v];
    64             }
    65             else{
    66                 swap(edge[i],edge[m--]);
    67             }
    68         }
    69         n=tn-1;
    70         root=id[root];
    71     }
    72     return res;
    73 }
    74 
    75 
    76 int main(){
    77     std::ios::sync_with_stdio(false);
    78     int n,m,r;
    79     cin>>n>>m>>r;
    80     for(int i=1;i<=m;i++){
    81         cin>>edge[i].u>>edge[i].v>>edge[i].cost;
    82     }
    83     int ans=zhuliu(r,n,m);
    84     cout<<ans<<endl;
    85 }
    View Code
  • 相关阅读:
    python 类
    python sys模块
    python os模块(2)
    python re模块
    python 最小公倍数
    python 最大公约数
    python datetime模块
    python 给定n,返回n以内的斐波那契数列
    python time模块
    python os模块(1)
  • 原文地址:https://www.cnblogs.com/Fighting-sh/p/9994314.html
Copyright © 2011-2022 走看看