HDU - 1083 Courses(二分图匹配)

二分图匹配的模板

 

二分图:如果顶点集 V可分割为两个互不相交的子集X和Y,并且图中每条边连接的两个顶点一个在 X中,另一个在 Y中,则称图G为二分图。

交替路:从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边…形成的路径叫交替路

增广路:两个端点都是未盖点的交替路叫做可增广路。

 

伪代码:

bool(u)

{

  for(u所连的点)

  {

    if  v不在交替路上

    {

      将v加入交替路

      if v点未匹配||有可能有增长路

      {

        标记;

        ture;

      }

    }

  }

  false;

}

 

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<stack>
 6 #include<queue>
 7 #include<cmath>
 8 #include<set>
 9 
10 
11 #define ll long long
12 #define mem(a,b) memset(a,b,sizeof(a))
13 #define inf 0x3f3f3f3f
14 
15 using namespace std;
16 
17 const int maxn=3e4+10;
18 
19 struct edge{
20     int u,v,next;
21 }e[maxn*2];
22 
23 int g[maxn*2],vis[maxn*2],dis[maxn*2],cheek[maxn];
24 int tot;
25 
26 void init()
27 {
28     mem(g,0);
29     mem(vis,0);
30     mem(e,0);
31     mem(dis,0);
32     tot=0;
33 }
34 
35 void make_edge(int u,int v)
36 {
37     e[++tot]=(edge){u,v,g[u]};
38     g[u]=tot;
39 }
40 
41 bool dfs(int u)
42 {
43     for(int i=g[u];i>0;i=e[i].next)
44     {
45         int v=e[i].v;
46         if(!cheek[v])//如果v不在交替路上
47         {
48             cheek[v]=1;//将v加入交替路
49             if(!vis[v]||dfs(vis[v]))//如果v点未被覆||有可能有增广路 标记
50             {
51                 //vis[u]=v;
52                 vis[v]=u;
53                 return true;//如果有增广路
54             }
55         }
56     }
57     return false;//无
58 }
59 
60 int hungarian(int n,int m)
61 {
62     int ans=0;
63     for(int u=m+1;u<=n+m;u++)//枚举一个集合的点
64     {
65         if(vis[u]==0)//未被覆盖
66         {
67             mem(cheek,0);
68             if(dfs(u))  ans++;//匹配++;
69         }
70     }
71     return ans;
72 }
73 
74 int main(){
75     int t;
76     scanf("%d",&t);
77     while(t--)
78     {
79         init();
80         int n,m;
81         scanf("%d%d",&n,&m);
82         for(int i=1;i<=n;i++)
83         {
84             int t;
85             scanf("%d",&t);
86             for(int j=1;j<=t;j++)
87             {
88                 int now;
89                 scanf("%d",&now);
90                 make_edge(m+i,now);
91                 //make_edge(now,m+i);
92             }
93         }
94         int temp=hungarian(n,m);
95         //cout<<temp<<endl;
96         cout<<(temp==n?"YES":"NO")<<endl;
97     }
98     return 0;
99 }

 

上一篇:PAT 1083 是否存在相等的差 (20 分)


下一篇:linux中的SGI(核间中断)IPI_RESCHEDULE详解