码迷,mamicode.com
首页 > 其他好文 > 详细

课程-二分图

时间:2016-09-03 16:29:08      阅读:114      评论:0      收藏:0      [点我收藏+]

标签:

http://www.luogu.org/problem/show?pid=2417#sub

题目描述

n个学生去p个课堂,每一个学生都有自己的课堂,并且每个学生只能去一个课堂,题目要求能够安排每一个课堂都有人吗?

输入输出格式

输入格式:

第一行是测试数据的个数,

每组测试数据的开始分别是p和n,

接着p行,每行的开始是这个课堂的学生人数m,接着m个数代表该课堂的学生编号 

输出格式:

如果该组数据能够这样安排就输出YES,否则输出NO。

 

经典模型,建二分图,根据学生和教室的关系,连容量为1的边,再增加S和T点,分别用容量1的边连所有学生和所有教室,跑一遍最大流,判断最大流是否等于教室数(当然可以用其他方法求最大匹配,不一定要用S,T点连边)

 1 #include<iostream>
 2 #include<vector>
 3 #include<queue>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn=100010;
 7 const int inf=1<<30;
 8 struct Edge{
 9     int from,to,flow,cap;
10 };
11 struct Dinic{
12     int vis[maxn],cur[maxn],d[maxn];
13     vector<Edge> edges;
14     vector<int> G[maxn];
15     int s,t;
16     void clear()
17     {
18         for(int i=0;i<maxn;i++) G[i].clear();
19         edges.clear();
20     }
21     void addEdge(int from,int to,int cap)
22     {
23         edges.push_back((Edge){from,to,0,cap});
24         G[from].push_back(edges.size()-1);
25         edges.push_back((Edge){to,from,0,0});
26         G[to].push_back(edges.size()-1);
27     }
28     int BFS()
29     {
30         memset(vis,0,sizeof(vis));
31         queue<int> Q;
32         Q.push(s);
33         vis[s]=1;
34         d[s]=0;
35         while(!Q.empty()){
36             int x=Q.front();Q.pop();
37             for(int i=0;i<G[x].size();i++){
38                 Edge& e=edges[G[x][i]];
39                 if(!vis[e.to]&&e.cap>e.flow){
40                     vis[e.to]=1;
41                     d[e.to]=d[x]+1;
42                     Q.push(e.to);
43                 }
44             }
45         }
46         return vis[t];
47     }
48     int DFS(int u,int a)
49     {
50         if(u==t||a==0) return a;
51         int flow=0,f;
52         for(int& i=cur[u];i<G[u].size();i++){
53             Edge& e=edges[G[u][i]];
54             if(d[e.to]==d[u]+1&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
55                 e.flow+=f;
56                 edges[G[u][i]^1].flow-=f;
57                 flow+=f;
58                 a-=f;
59                 if(!a) break;
60             }
61         }
62         return flow;
63     }
64     int MaxFlow(int ss,int tt)
65     {
66         int ans=0;
67         s=ss,t=tt;
68         while(BFS()){
69             memset(cur,0,sizeof(cur));
70             ans+=DFS(s,inf);
71         }
72         return ans;
73     }
74 };
75 Dinic solver;
76 int main()
77 {
78     int n,p,T,m,a;
79     cin>>T;
80     while(T--)
81     {
82         solver.clear();
83         cin>>p>>n;
84         for(int i=2;i<=n+1;i++) solver.addEdge(1,i,1);
85         for(int i=n+2;i<=n+p+1;i++) solver.addEdge(i,n+p+2,1);
86         for(int i=1;i<=p;i++){
87             cin>>m;
88             while(m--){
89                 cin>>a;
90                 solver.addEdge(a+1,n+i+1,1);
91             }
92         }
93         if(solver.MaxFlow(1,n+p+2)==p) cout<<"YES\n";
94         else cout<<"NO\n";
95     }
96     return 0;
97 }

 

课程-二分图

标签:

原文地址:http://www.cnblogs.com/gzhonghui/p/5837163.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!