zoukankan      html  css  js  c++  java
  • cogs426 血帆海盗 最小割定理

    链接:http://cogs.pro/cogs/problem/problem.php?pid=426

    题意:在二分图中找出一类边的数量,这类边的特点是:砍掉这条边之后整个二分图最大匹配数量减少。

    首先跑一个裸的二分图最大匹配,找到所有的连接方式。可能有人会认为最大匹配数就是所求结果,但其实不是,因为我们可以举出一个例子:

    在这张图中,最大匹配数是1,但是显然种类是0种,因此我们还需要想其他的思路。

    以样例为例,考虑跑完二分图匹配之后的增广路:

    其中,虚线表示增广后的反向边。我们可以看出有些点是在同一个强连通分量上的,砍掉这些点之间的边毫无意义。

    因此思路就出来了:跑完二分图最大匹配后在残量网络上尬舞跑Tarjan,搞出强连通分量,随后枚举每一条被增广的边,如果起点终点在同一强连通分量内,ans--。

    问题得解。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 const int maxn=200005;
      7 struct node
      8 {
      9     int from,to,flow,next;
     10 }edge[maxn<<1];
     11 int head[maxn],tot;
     12 void addedge(int u,int v,int w)
     13 {
     14     edge[tot]=(node){u,v,w,head[u]};head[u]=tot++;
     15     edge[tot]=(node){v,u,0,head[v]};head[v]=tot++;
     16 }
     17 int n,m,S,T,exist[maxn];
     18 #include<queue>
     19 const int inf=0x7fffffff;
     20 int dis[maxn];
     21 bool bfs()
     22 {
     23     memset(dis,0,sizeof(dis));
     24     dis[S]=1;
     25     queue<int>q;q.push(S);
     26     while(!q.empty())
     27     {
     28         int u=q.front();q.pop();
     29         for(int i=head[u];i!=-1;i=edge[i].next)
     30         {
     31             int v=edge[i].to;
     32             if(!dis[v]&&edge[i].flow>0)
     33             {
     34                 dis[v]=dis[u]+1;
     35                 q.push(v);
     36             }
     37         }
     38     }
     39     return dis[T]!=0;
     40 }
     41 int dfs(int pos,int flow)
     42 {
     43     if(pos==T||!flow)return flow;
     44     int ans=0;
     45     for(int i=head[pos];i!=-1;i=edge[i].next)
     46     {
     47         int v=edge[i].to;
     48         if(dis[v]==dis[pos]+1&&edge[i].flow>0)
     49         {
     50             int t=dfs(v,min(flow,edge[i].flow));
     51             if(t)
     52             {
     53                 edge[i].flow-=t;
     54                 edge[i^1].flow+=t;
     55                 ans+=t;
     56                 if(ans==flow)break;
     57             }
     58         }
     59     }
     60     return ans;
     61 }
     62 int dfn[maxn],low[maxn],cnt,scnt,belong[maxn],instack[maxn];
     63 #include<stack>
     64 stack<int>s;
     65 void dfs(int pos)
     66 {
     67     dfn[pos]=low[pos]=++cnt;s.push(pos);instack[pos]=1;
     68     for(int i=head[pos];i!=-1;i=edge[i].next)
     69     {
     70         int v=edge[i].to;
     71         if(edge[i].flow>0)
     72         {
     73             if(!dfn[v])
     74             {
     75                 dfs(v);
     76                 low[pos]=min(low[pos],low[v]);
     77             }
     78             else if(instack[v])low[pos]=min(low[pos],dfn[v]);
     79         }
     80     }
     81     if(low[pos]==dfn[pos])
     82     {
     83         scnt++;int k;
     84         do
     85         {
     86             k=s.top();s.pop();
     87             belong[k]=scnt;
     88             instack[k]=0;
     89         }while(k!=pos);
     90     }
     91 }
     92 int haha()
     93 {
     94     freopen("bloodsail.in","r",stdin);
     95     freopen("bloodsail.out","w",stdout);
     96     memset(head,-1,sizeof(head));
     97     scanf("%d%d",&n,&m);
     98     for(int i=1;i<=m;i++)
     99     {
    100         int x,y;scanf("%d%d",&x,&y);
    101         addedge(x,y,1);
    102         exist[x]=exist[y]=1;
    103     }
    104     S=0,T=n+1;
    105     int mid=n>>1;
    106     for(int i=1;i<=mid;i++)
    107         if(exist[i])addedge(S,i,1);
    108     for(int i=mid+1;i<=n;i++)
    109         if(exist[i])addedge(i,T,1);
    110     int ans=0;
    111     while(bfs())
    112         ans+=dfs(S,inf);
    113     for(int i=1;i<=n;i++)
    114         if(!dfn[i])dfs(i);
    115     for(int i=1;i<=mid;i++)
    116         for(int j=head[i];j!=-1;j=edge[j].next)
    117         {
    118             int v=edge[j].to;
    119             if(!edge[j].flow&&v&&belong[i]==belong[v])ans--;
    120         }
    121     printf("%d
    ",ans);
    122 }
    123 int sb=haha();
    124 int main(){;}
    cogs426
    只要是活着的东西,就算是神我也杀给你看。
  • 相关阅读:
    url中的jsessionid解释
    电脑双网卡配置
    jedis api使用
    RedisTemplate访问Redis数据结构
    动态jdk启动项目
    导入导出Excel工具类ExcelUtil
    git超详细教程
    Linux配置SSH免用户免密码登陆
    hdfs shell的基本操作以及hdfsWeb查看文件
    清除redis的特定前缀的key
  • 原文地址:https://www.cnblogs.com/Loser-of-Life/p/7261482.html
Copyright © 2011-2022 走看看