zoukankan      html  css  js  c++  java
  • How Many to Be Happy? (最小生成树进一步理解 + 最小割)

    How Many to Be Happy? (最小生成树进一步理解 + 最小割)

     最小生成树:MST性质(学习博客:here

    题解:我们想让某一条边一定是最小生成树中的边,只要找到任意一种点集的分配,使得这条边的两个顶点在不同的分配中且边权是连接这两个分配的所有边中最小的那一个。显然只有边权比它小的边才会影响它是不是在最小生成树中。于是我们可以只在图中保留边权小于当前边权的边,看看是否能找到一种点集的分配。显然当这个边的两个顶点在新图中仍然连通时,我们找不到这种分配,于是就需要砍掉若干边使两顶点不连通,于是题目就转化为了最小割问题。(来自大佬博客:here

    AC_Code:

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 const int maxn = 1e5+10;
      4 const int inf = 0x3f3f3f3f;
      5 typedef long long ll;
      6 
      7 
      8 struct node{
      9     ll to,nxt,w;
     10 }e[maxn<<1];
     11 
     12 struct edge{
     13     ll u,v;
     14     ll w;
     15     bool operator < (const edge &o) const{
     16         return w<o.w;
     17     }
     18 }E[maxn];
     19 
     20 ll head[maxn],tot,dep[maxn];
     21 ll n,m;
     22 ll S,T;//源点,汇点
     23 
     24 void init(){
     25     memset(head,-1,sizeof(head));
     26     tot = 0;
     27 }
     28 
     29 void addedge(ll u,ll v,ll w){
     30     e[tot].to=v; e[tot].w=w; e[tot].nxt=head[u]; head[u]=tot++;
     31 }
     32 
     33 bool bfs(ll st,ll ed){
     34     memset(dep,-1,sizeof(dep));
     35     queue<ll>que;
     36     while( !que.empty()) que.pop();
     37     que.push(st);
     38     dep[st]=0;
     39     ll u;
     40     while( !que.empty()){
     41         u=que.front();que.pop();
     42         for(ll i=head[u]; ~i; i=e[i].nxt){
     43             ll v=e[i].to;
     44             if( dep[v]==-1 && e[i].w>0 ){
     45                 dep[v]=dep[u]+1;
     46                 que.push(v);
     47                 if( v==ed ) return true;
     48             }
     49 
     50         }
     51     }
     52     return dep[ed]!=-1;
     53 }
     54 
     55 ll dfs(ll st,ll ed,ll flow){
     56     if( st==ed || flow==0 ) return flow;
     57     ll curr=0;
     58     for(ll i=head[st];~i;i=e[i].nxt){
     59         ll v=e[i].to;
     60         ll val=e[i].w;
     61         if( dep[st]+1==dep[v] && val>0 ){
     62             ll d=dfs(v,ed,min(val,flow));
     63             if( d>0 ){
     64                 e[i].w-=d;e[i^1].w+=d;
     65                 curr+=d;flow-=d;
     66                 if( flow==0 ) break;
     67             }
     68         }
     69     }
     70     if( curr==0 ) dep[st]=inf;
     71     return curr;
     72 }
     73 
     74 ll Dinic(ll st,ll ed){
     75     for(ll i=0;i<=tot;i++) e[i].w = 1;//注意这里,因为e[i].w有被改动这里要初始化
     76     ll flow=0;
     77     while( bfs(st,ed) ){
     78         flow+=dfs(st,ed,inf);
     79     }
     80     return flow;
     81 }
     82 
     83 int main()
     84 {
     85     init();
     86     scanf("%lld%lld",&n,&m);
     87     for(ll i=1;i<=m;i++){
     88         scanf("%lld%lld%lld",&E[i].u,&E[i].v,&E[i].w);
     89     }
     90     sort(E+1, E+1+m);
     91     init();
     92     ll ans = 0;
     93     ll r = 1;
     94     for(ll i=1;i<=m;i++){
     95         while( E[r].w<E[i].w ){//注意要权值小于这条边才对这条边有影响,大于等于都没有影响
     96             addedge(E[r].u, E[r].v, 1);
     97             addedge(E[r].v, E[r].u, 1);
     98             r ++ ;
     99         }
    100         S=E[i].u;
    101         T=E[i].v;
    102         ans += Dinic(S,T);
    103     }
    104     printf("%lld
    ",ans);
    105     return 0;
    106 }
  • 相关阅读:
    实现CA和证书申请
    1.ssh端口
    1.对称加密6和7的操作
    关于网页访问并发量,统计前十,防火墙
    双指针法
    并查集
    c++常用函数
    vector常用方法
    贪心算法
    字符串类问题
  • 原文地址:https://www.cnblogs.com/wsy107316/p/14109213.html
Copyright © 2011-2022 走看看