zoukankan      html  css  js  c++  java
  • hdu 3452(最小割)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3452

    思路:一颗带边权的树,最小割求树根和叶子结点不连通。可设汇点为n+1,注意只用叶子结点才能和汇点连容量为inf的边。

    View Code
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<set>
      6 using namespace std;
      7 #define MAXN 2222
      8 #define MAXM 222222
      9 #define inf 1<<30
     10 
     11 struct Edge{
     12     int v,cap,next;
     13 }edge[MAXM];
     14 
     15 
     16 int head[MAXN];
     17 int pre[MAXN];
     18 int cur[MAXN];
     19 int level[MAXN];
     20 int gap[MAXN];
     21 int NV,NE,n,m,vs,vt;
     22 
     23 void Insert(int u,int v,int cap,int cc=0){
     24     edge[NE].v=v;edge[NE].cap=cap;
     25     edge[NE].next=head[u];head[u]=NE++;
     26 
     27     edge[NE].v=u;edge[NE].cap=cc;
     28     edge[NE].next=head[v];head[v]=NE++;
     29 }
     30 
     31 
     32 int SAP(int vs,int vt){
     33     memset(pre,-1,sizeof(pre));
     34     memset(level,0,sizeof(level));
     35     memset(gap,0,sizeof(gap));
     36     for(int i=0;i<=NV;i++)cur[i]=head[i];
     37     int u=pre[vs]=vs,maxflow=0,aug=-1;
     38     gap[0]=NV;
     39     while(level[vs]<NV){
     40 loop:
     41         for(int &i=cur[u];i!=-1;i=edge[i].next){
     42             int v=edge[i].v;
     43             if(edge[i].cap&&level[u]==level[v]+1){
     44                 aug==-1?aug=edge[i].cap:aug=min(aug,edge[i].cap);
     45                 pre[v]=u;
     46                 u=v;
     47                 if(v==vt){
     48                     maxflow+=aug;
     49                     for(u=pre[u];v!=vs;v=u,u=pre[u]){
     50                         edge[cur[u]].cap-=aug;
     51                         edge[cur[u]^1].cap+=aug;
     52                     }
     53                     aug=-1;
     54                 }
     55                 goto loop;
     56             }
     57         }
     58         int minlevel=NV;
     59         for(int i=head[u];i!=-1;i=edge[i].next){
     60             int v=edge[i].v;
     61             if(edge[i].cap&&minlevel>level[v]){
     62                 cur[u]=i;
     63                 minlevel=level[v];
     64             }
     65         }
     66         if(--gap[level[u]]==0)break;
     67         level[u]=minlevel+1;
     68         gap[level[u]]++;
     69         u=pre[u];
     70     }
     71     return maxflow;
     72 }
     73 
     74 int main(){
     75     while(~scanf("%d%d",&n,&m)&&n&&m){
     76         vs=m,vt=n+1,NV=vt,NE=0;
     77         memset(head,-1,sizeof(head));
     78         set<int>st[MAXN];
     79         for(int i=1;i<=n-1;i++){
     80             int u,v,w;
     81             scanf("%d%d%d",&u,&v,&w);
     82             Insert(u,v,w);
     83             Insert(v,u,w);
     84             st[u].insert(v);
     85             st[v].insert(u);
     86         }
     87         //只有叶子结点才与汇点连容量为inf的边
     88         for(int i=0;i<=n;i++){
     89             if(st[i].size()==1&&i!=vs)Insert(i,vt,inf);
     90         }
     91         printf("%d\n",SAP(vs,vt));
     92     }
     93     return 0;
     94 }
     95 
     96 
     97     
     98 
     99 
    100 
    101 
    102 
    103     
    104     
    105     
  • 相关阅读:
    CSS 控制table 滑动及调整列宽等问题总结
    Java读取properties文件
    水晶报表打印
    C# 运行时序列化
    C#attribute-----------初级
    c# 单元测试工程如何取得当前项目路径
    C# 字段、属性、成员变量
    水晶报表主子报表分页问题
    从0打卡leetcode之day 3 -- 最大子序列和
    从零打卡leetcode之day 2---两数相加
  • 原文地址:https://www.cnblogs.com/wally/p/3068854.html
Copyright © 2011-2022 走看看