USACO4.2.2 The Perfect Stall (stall4)

来源:互联网 发布:淘宝steam离线游戏 编辑:程序博客网 时间:2024/06/05 22:51

二分图匹配

1. 最简单的匈牙利算法,可以看下面这个生动形象的匈牙利算法讲解

http://blog.csdn.net/dark_scope/article/details/8880547


#include <cstdio>  #include <cstring>  #include <algorithm>  #include <vector>    using namespace std;    int n, m;  vector<int> edges[205];  int mat[205];  int done[205];    void addEdge(int a, int b) {      edges[a].push_back(b);  }    bool dfs(int k) {      for (int i = 0; i < edges[k].size(); i++)     {          int j = edges[k][i];          if(done[j]) continue;          done[j] = 1;          if (!mat[j] || dfs(mat[j]))         {              mat[j] = k;              return true;          }      }      return false;  }    int match() {      int ans = 0;      for (int i = 1; i <= n; i++)     {          if (dfs(i)) ans++;          memset(done, 0, sizeof(done));      }      return ans;  }    int main() {      freopen("stall4.in", "r", stdin);      freopen("stall4.out", "w", stdout);      scanf("%d %d", &n, &m);      int a;      for (int i = 1; i <= n; i++)     {          scanf("%d", &a);          int b;          for (int j = 1; j <= a; j++)         {              scanf("%d", &b);              addEdge(i, b);          }      }      int ans = match();            printf("%d\n", ans);      return 0;  }  


2.数据范围不大,网络流也能过,用模板,可以锻炼建图能力


/*ID:xsy97051LANG:C++TASK:stall4*/#include <iostream>#include <cstdio>#include <queue>#include <vector>#include <algorithm>#include <cstring>#define INF 0x3f3f3f3f#define MAXV 10000 using namespace std;struct Edge {int from, to, cap, flow;};    //弧  从from到to,容量cap, 流量flowint V,E,S,T;         //V 个点  E条弧   从S到T vector<Edge> edges;  // edges[e] edges[e ^ 1] 反向弧vector<int> G[MAXV]; // 邻接表 G[i][j]表示节点i的第j条边在edges中的序号bool vis[MAXV];// build使用,表示的i条边有没有被标号过int layer[MAXV];// 节点i的层int cur[MAXV];// 当前弧下标//插入两条弧,一条是它本身,反向弧void addEdge(int from, int to, int cap) {Edge temp; temp.from=from;   temp.to=to;temp.cap=cap;temp.flow=0;edges.push_back(temp);temp.from=to; temp.to=from;temp.cap=0;    temp.flow=0;edges.push_back(temp);E=edges.size();G[from].push_back(E-2);G[to].push_back(E-1);}//建图  return是否存在s-t路径bool build() {memset(vis, 0, sizeof(vis));queue<int> q;q.push(S);layer[S]=0;vis[S]=1;while(!q.empty()){int x=q.front();q.pop();for(int i=0;i<G[x].size();i++) {Edge & e = edges[G[x][i]];if (!vis[e.to] && e.cap > e.flow)    // 只考虑残量网络的弧 { vis[e.to]=1;layer[e.to]=layer[x] + 1;q.push(e.to);}}}return vis[T];}//dfs寻找增广路    x当前节点   a所有弧最小残量    return流量int dfs(int x, int a) {if (x==T || a==0) return a;int flow=0;int f;for (int &i=cur[x];i<G[x].size();i++){Edge & e = edges[G[x][i]];if (layer[x]+1==layer[e.to] && (f=dfs(e.to, min(a, e.cap-e.flow)))!= 0) {e.flow += f;edges[G[x][i]^1].flow -= f;flow += f;a -= f;if (!a)break;}}return flow;}int dinic(int s, int t){S=s;T=t;int flow=0;while(build()){memset(cur,0,sizeof(cur));flow += dfs(s,INF);}return flow;}int main (){freopen("stall4.in","r",stdin);freopen("stall4.out","w",stdout);int n,m;cin>>n>>m;V=n+m+2;    int x,y; for(int i=2;i<=n+1;i++){addEdge(1,i,1);cin>>x;for(int j=1;j<=x;j++){cin>>y;addEdge(i,y+n+1,1);}}for(int j=n+2;j<=n+m+1;j++){addEdge(j,n+m+2,1);}cout<<dinic(1,V)<<endl;return 0;}




0 0