zoukankan      html  css  js  c++  java
  • HDU 3452 Bonsai

    题意:给出一颗树和树根,每条树边都有边权,要你砍断一些边,使得所有的叶子节点都与根节点分离,且要求砍断的边权之和最小。

    以树根root为源点S,添加一个汇点T,对所有的非跟叶子节点i,加边(i,T,inf),求最小割即可。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define INF 1<<30
     6 #define maxn 1010
     7 #define maxm 10000
     8 using namespace std;
     9 
    10 int u[maxm],v[maxm],next[maxm],w[maxm];
    11 int first[maxn],d[maxn],work[maxn],q[maxn],vis[maxn];
    12 int e,S,T;
    13 int degree[maxn];
    14 
    15 void init(){
    16     e = 0;
    17     memset(first,-1,sizeof(first));
    18 }
    19 
    20 void add_edge(int a,int b,int c){
    21     u[e] = a;v[e] = b;next[e] = first[a];w[e] = c;first[a] = e++;
    22     u[e] = b;v[e] = a;next[e] = first[b];w[e] = 0;first[b] = e++;
    23 }
    24 
    25 int bfs(){
    26     int rear = 0;
    27     memset(d,-1,sizeof(d));
    28     d[S] = 0;q[rear++] = S;
    29     for(int i = 0;i < rear;i++){
    30         for(int j = first[q[i]];j != -1;j = next[j])
    31             if(w[j] && d[v[j]] == -1){
    32                 d[v[j]] = d[q[i]] + 1;
    33                 q[rear++] = v[j];
    34                 if(v[j] == T)   return 1;
    35             }
    36     }
    37     return 0;
    38 }
    39 
    40 int dfs(int cur,int a){
    41     if(cur == T)    return a;
    42     for(int &i = work[cur];i != -1;i = next[i]){
    43         if(w[i] && d[v[i]] == d[cur] + 1)
    44             if(int t = dfs(v[i],min(a,w[i]))){
    45                 w[i] -= t;w[i^1] += t;
    46                 return t;
    47             }
    48     }
    49     return 0;
    50 }
    51 
    52 int dinic(){
    53     int ans = 0;
    54     while(bfs()){
    55         memcpy(work,first,sizeof(first));
    56         while(int t = dfs(S,INF))   ans += t;
    57     }
    58     return ans;
    59 }
    60 
    61 int main()
    62 {
    63     int n,root;
    64     while(scanf("%d%d",&n,&root) == 2){
    65         if(!n && !root) break;
    66         memset(degree,0,sizeof(degree));
    67         S = root,T = n+1;
    68         init();
    69         for(int i = 0;i < n-1;i++){
    70             int a,b,c;
    71             scanf("%d%d%d",&a,&b,&c);
    72             add_edge(a,b,c);
    73             add_edge(b,a,c);
    74             degree[a]++;degree[b]++;
    75         }
    76         for(int i = 1;i <= n;i++){
    77             if(degree[i] == 1 && i != root)
    78                 add_edge(i,T,INF);
    79         }
    80         printf("%d
    ",dinic());
    81     }
    82     return 0;
    83 }
    View Code
  • 相关阅读:
    Oracle 数据库(oracle Database)Select 多表关联查询方式
    Mysql下在某一列后即表的某一位置添加新列的sql语句
    通过javascript库JQuery实现页面跳转功能代码
    Linux 流量监控软件 NetHogs
    php和mysql中uft8中文编码乱码的几种解决办法
    Codeigniter 2.0多目录配置详解
    PHP编程54条必知
    Ubuntu 安装XAMPP集成环境软件包 与 运行WordPress 的简单方法
    Ubuntu 12.04 lts / Win7双系统安装方法
    smarty的配置使用
  • 原文地址:https://www.cnblogs.com/zhexipinnong/p/3398594.html
Copyright © 2011-2022 走看看