zoukankan      html  css  js  c++  java
  • HDU5765 Bonds 最小割极

    http://acm.hdu.edu.cn/showproblem.php?pid=5765

    题意:无向连通图,问每条边在几个最小割极上

    思路:用位压形式,表示边的关系。g[1<<i]=1<<x  表示第i个点与哪几个点相连。然后,处理出每种点集和哪些点相连。每个点构成一个连通图,所以枚举当前点集,可以得到所有连通图的点集,计算出数量,用高维前缀和处理所有包含i点的连通块

    ans=(所有连通块-同时包含(i,j)的连通块数目)/2  应为以(i,j)为割边的连通块,删除该边以后,数量加倍,所以除2

     1 #include<iostream>
     2 #include<string>
     3 #include<algorithm>
     4 #include<cstdlib>
     5 #include<cstdio>
     6 #include<set>
     7 #include<map>
     8 #include<vector>
     9 #include<cstring>
    10 #include<stack>
    11 #include<cmath>
    12 #include<queue>
    13 #include <conio.h>
    14 #define clc(a,b) memset(a,b,sizeof(a))
    15 #include <bits/stdc++.h>
    16 const int maxn = 20005;
    17 const int inf=0x3f3f3f3f;
    18 const double pi=acos(-1);
    19 typedef long long LL;
    20 using namespace std;
    21 //const LL MOD = 1e9+7;
    22 void fre(){freopen("in.txt","r",stdin);}
    23 inline int lb(int x){return x&(-x);}
    24 const int N=1<<21;
    25 
    26 int g[N],a[N],u[500],v[500];
    27 bool vis[N];
    28 int sum[N];
    29 int main(){
    30     int T;
    31     scanf("%d",&T);
    32     for(int cas=1;cas<=T;cas++){
    33         int n,m;
    34         scanf("%d%d",&n,&m);
    35         for(int i=1;i<1<<n;i++) sum[i]=0,g[i]=0,vis[i]=false;
    36         for(int i=0;i<m;i++){
    37             int x,y;
    38             scanf("%d%d",&x,&y);
    39             u[i]=x,v[i]=y;
    40             g[1<<x]|=1<<y;
    41             g[1<<y]|=1<<x;
    42         }
    43         for(int i=1;i<1<<n;i++) g[i]|=g[i-lb(i)]|g[lb(i)];
    44         int l=0,r=0;
    45         for(int i=0;i<n;i++) vis[a[r++]=1<<i]=true;
    46         while(l<r){
    47            int c=a[l++];
    48            int res=g[c]^(g[c]&c);
    49            while(res){
    50              int tem=lb(res)|c;
    51              if(!vis[tem]) vis[a[r++]=tem]=true;
    52              res-=lb(res);
    53            }
    54         }
    55         int all=0;
    56         for(int i=1;i<1<<n;i++){
    57             int j=(1<<n)-1;
    58             j^=i;
    59             if(vis[i]&&vis[j]){
    60                 sum[i]++,sum[j]++,all++;
    61             }
    62         }
    63         for(int j=0;j<n;j++){
    64             for(int i=(1<<n)-1;i>=1;i--)
    65                 if(!(i&(1<<j))) sum[i]+=sum[i^(1<<j)];
    66         }
    67         printf("Case #%d: ",cas);
    68         for(int i=0;i<m;i++){
    69             printf("%d",(all-sum[(1<<u[i])|(1<<v[i])])/2);
    70             if(i==m-1) cout<<endl;
    71             else cout<<" ";
    72         }
    73     }
    74     return 0;
    75 
    76 }
  • 相关阅读:
    Java之ServiceLoader
    docker学习(3)--Dockfile详解
    docker学习(2)--基础命令
    docker学习(1)--基础概念
    dubbo学习(1)--简单的入门搭建实例
    Flume搭建及学习(基础篇)
    VM下--Linux根分区磁盘扩容
    Windows10下简单搭建zookeeper
    Windows10下搭建TensorFlow环境
    cmath库函数
  • 原文地址:https://www.cnblogs.com/ITUPC/p/5728468.html
Copyright © 2011-2022 走看看