zoukankan      html  css  js  c++  java
  • 一般图最大匹配

    转载:https://www.cnblogs.com/xiongtao/p/11189452.html

    题意:有一个n个点,m条边的图  ,给出每个点的度数,问是否可以成为该图的子图。

    样例:

    n个点  m条边 每个点的度数

    4 4
    1 2
    3 4
    2 3
    1 4
    1
    2
    1
    0
      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<queue>
      6 #define inf 0x3f3f3f3f
      7 using namespace std;
      8 typedef long long ll;
      9 const int maxn=1050;
     10 bool g[maxn][maxn],inque[maxn],inpath[maxn];
     11 bool inhua[maxn];
     12 int st,ed,newbase,ans,n;
     13 int base[maxn],pre[maxn],match[maxn];
     14 int head,tail,que[maxn]; 
     15 int x[maxn],y[maxn],f[maxn],mp[maxn][maxn],ne,np;
     16 
     17 void Push(int u)
     18 {
     19     que[tail]=u;
     20     tail++;
     21     inque[u]=1;
     22 }
     23 int Pop()
     24 {
     25     int res=que[head];
     26     head++;
     27     return res;
     28 }
     29 
     30 int lca(int u,int v)//寻找公共花祖先 
     31 {
     32     memset(inpath,0,sizeof(inpath));
     33     while(1)
     34     {
     35         u=base[u];
     36         inpath[u]=1;
     37         if(u==st) break;
     38         u=pre[match[u]];    
     39     }    
     40     while(1)
     41     {
     42         v=base[v];
     43         if(inpath[v]) break;
     44         v=pre[match[v]];
     45     }
     46     return v;
     47 } 
     48 void reset(int u)//缩环 
     49 {
     50     int v;
     51     while(base[u]!=newbase)
     52     {
     53         v=match[u];
     54         inhua[base[u]]=inhua[base[v]]=1;
     55         u=pre[v];
     56         if(base[u]!=newbase) pre[u]=v;
     57     }
     58 } 
     59 void contract(int u,int v)//
     60 {
     61     newbase=lca(u,v);
     62     memset(inhua,0,sizeof(inhua));
     63     reset(u);
     64     reset(v);
     65     if(base[u]!=newbase) pre[u]=v;
     66     if(base[v]!=newbase) pre[v]=u;
     67     for(int i=1;i<=n;i++)
     68     {
     69         if(inhua[base[i]]){
     70             base[i]=newbase;
     71             if(!inque[i])
     72                 Push(i);
     73         }
     74     }
     75 }
     76 void findaug()
     77 {
     78     memset(inque,0,sizeof(inque));
     79     memset(pre,0,sizeof(pre));
     80     for(int i=1;i<=n;i++)//并查集 
     81         base[i]=i;
     82     head=tail=1;
     83     Push(st);
     84     ed=0;
     85     while(head<tail)
     86     {
     87         int u=Pop();
     88         for(int v=1;v<=n;v++)
     89         {
     90             if(g[u][v]&&(base[u]!=base[v])&&match[u]!=v)
     91             {
     92                 if(v==st||((match[v]>0) && pre[match[v]]>0))//成环 
     93                     contract(u,v);
     94                 else if(pre[v]==0)
     95                 {
     96                     pre[v]=u;
     97                     if(match[v]>0)
     98                         Push(match[v]);
     99                     else//找到增广路 
    100                     {
    101                         ed=v;
    102                         return ;    
    103                     }    
    104                 }
    105             }
    106         }
    107     }
    108 }
    109 void aug()
    110 {
    111     int u,v,w;
    112     u=ed;
    113     while(u>0)
    114     {
    115         v=pre[u];
    116         w=match[v];
    117         match[v]=u;
    118         match[u]=v;
    119         u=w;
    120     }
    121 }
    122 void edmonds()//匹配 
    123 {
    124     memset(match,0,sizeof(match));
    125     for(int u=1;u<=n;u++)
    126     {
    127         if(match[u]==0)
    128         {
    129             st=u;
    130             findaug();//以st开始寻找增广路 
    131             if(ed>0) aug();//找到增广路  重新染色,反向 
    132         }
    133     }
    134 }
    135 //以上是带花树求最大匹配算法  不用看 
    136  
    137 void create()//建图 
    138 {
    139     n=0;
    140     memset(g,0,sizeof(g));
    141     for(int i=1;i<=np;i++)
    142         for(int j=1;j<=f[i];j++)
    143             mp[i][j]=++n;//拆点,给每个度的点编号 
    144     for(int i=0;i<ne;i++)
    145     {//此时n+1代表x,n+2代表y 
    146         for(int j=1;j<=f[x[i]];j++)
    147             g[mp[x[i]][j]][n+1]=g[n+1][mp[x[i]][j]]=1;//每个度的点与对应的x,y相连 
    148         for(int j=1;j<=f[y[i]];j++)
    149             g[mp[y[i]][j]][n+2]=g[n+2][mp[y[i]][j]]=1;
    150         g[n+1][n+2]=g[n+2][n+1]=1;//x与y相连 
    151         n+=2;
    152     }    
    153 }
    154 void print()
    155 {
    156     ans=0;
    157     for(int i=1;i<=n;i++)
    158         if(match[i]!=0)
    159         {
    160             ans++;
    161 //            if(match[i]>i)
    162 //            cout<<"_____"<<i<<' '<<match[i]<<endl;
    163         }
    164     //cout<<"******"<<ans<<' '<<n<<endl;
    165     if(ans==n)    printf("YES
    ");
    166     else    printf("NO
    ");
    167 }
    168 int main()
    169 {
    170 
    171     //np点数   ne边数
    172     while(~scanf("%d%d", &np, &ne))
    173     {
    174         //f[i]每个点的度数
    175         for(int i=1;i<=np;i++)
    176             scanf("%d",&f[i]);
    177         //存边
    178         for(int i=0;i<ne;i++)
    179             scanf("%d%d",&x[i],&y[i]);
    180 
    181         create(); //建图
    182         edmonds(); //匹配
    183         print();    //打印答案
    184     }     
    185     return 0;
    186 }
  • 相关阅读:
    RAW和JPEG的区别_ZT
    用户自定义基元UDP_ZT
    UDP用户自定义原语
    SR锁存器
    Matlab实现Butterworth滤波器 分类: 图像处理 2014-06-02 00:05 527人阅读 评论(0) 收藏
    egrep命令的实现 分类: 编译原理 2014-06-01 23:41 329人阅读 评论(0) 收藏
    随机L系统分形树 分类: 计算机图形学 2014-06-01 23:27 376人阅读 评论(0) 收藏
    matlab实现算术编解码 分类: 图像处理 2014-06-01 23:01 357人阅读 评论(0) 收藏
    命名管道实现进程间通信--石头、剪刀、布游戏 分类: linux 2014-06-01 22:50 467人阅读 评论(0) 收藏
    互斥锁与条件变量应用 2014-06-01 22:20 328人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/SSummerZzz/p/13331417.html
Copyright © 2011-2022 走看看