hihoCoder 1122 二分图最大匹配 最大流

来源:互联网 发布:时文朝 银联数据 编辑:程序博客网 时间:2024/05/29 10:33

题意

  • 求二分图最大匹配

思路

  • 没有用匈牙利算法,而是试了试要带去的两个最大流模板。。
  • 就是加一个源点,一个汇点,源到二分图集合1的点加一个流量为1的边,集合1到集合2的边设置为流量1,集合2的点到汇点加入流量1的边

实现

  • 模板1实现
#include <iostream>#include <cstring>#include <cmath>#include <algorithm>#include <queue>#include <cstdio> #include <vector>using namespace std;const int MAXN = 2000;const int maxn = 2000;//最大流ISAP部分const int MAXM = 20005;const int INF = 0x3f3f3f3f;struct Edge{    int to,next,cap,flow;}edge[MAXM];int tol;int head[MAXN];int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];void init(){    tol = 0;    memset(head,-1,sizeof(head));}void addedge(int u,int v,int w,int rw = 0){    edge[tol].to = v;    edge[tol].cap = w;    edge[tol].next = head[u];    edge[tol].flow = 0;    head[u] = tol++;    edge[tol].to = u;    edge[tol].cap = rw;    edge[tol].next = head[v];    edge[tol].flow = 0;    head[v] = tol++;}int sap(int start,int end,int N){    memset(gap,0,sizeof(gap));    memset(dep,0,sizeof(dep));    memcpy(cur,head,sizeof(head));    int u = start;    pre[u] = -1;    gap[0] = N;    int ans = 0;    while(dep[start] < N)    {        if(u == end)        {            int Min = INF;            for(int i = pre[u]; i != -1;i = pre[edge[i^1].to])                if(Min > edge[i].cap - edge[i].flow)                    Min = edge[i].cap - edge[i].flow;            for(int i = pre[u];i != -1;i = pre[edge[i^1].to])            {                edge[i].flow += Min;                edge[i^1].flow -= Min;            }            u = start;            ans += Min;            continue;        }        bool flag = false;        int v;        for(int i = cur[u];i != -1;i = edge[i].next)        {            v = edge[i].to;            if(edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u])            {                flag = true;                cur[u] = pre[v] = i;                break;            }        }        if(flag)        {            u = v;            continue;        }        int Min = N;        for(int i = head[u];i != -1;i = edge[i].next)            if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)            {                Min = dep[edge[i].to];                cur[u] = i;            }        gap[dep[u]]--;        if(!gap[dep[u]])return ans;        dep[u] = Min+1;        gap[dep[u]]++;        if(u != start)u = edge[pre[u]^1].to;    }    return ans;}//the end of 最大流部分int vis[maxn];vector<int> g[maxn];#define pb push_backvoid dfs(int u){    for (int e=0;e<g[u].size();e++){        int v = g[u][e];        if (vis[v] == -1){            vis[v] = (vis[u] ^ 1);            dfs(v);        }    }}int main(){    int n,m;    cin>>n>>m;    int u,v;    for (int i=0;i<m;i++){        scanf("%d%d",&u,&v);        g[u].pb(v);        g[v].pb(u);    }    memset(vis,-1,sizeof(vis));    for (int i=1;i<=n;i++){        if (vis[i] == -1){            vis[i] = 0;            dfs(i);        }           }    init();         for (int i=1;i<=n;i++){        if (vis[i] == 0){            addedge(0,i,1);            for (int e=0;e<g[i].size();e++){                v = g[i][e];                addedge(i,v,1);            }        }        else{            addedge(i,n+1,1);        }    }    cout << sap(0,n+1,n+2) << "\n";    return 0;}
  • 实现2
#include <iostream>#include <cstring>#include <cmath>#include <algorithm>#include <queue>#include <cstdio> #include <vector>using namespace std;const int maxn = 2000;const int inf = 0x3f3f3f3f;struct EdmondsKarp{    //用到外部变量maxn,maxm,具体使用不非得按照模板     int n,m;    int g[maxn][maxn];    int flow[maxn];    int path[maxn];    queue<int> q;     void init(int nn=0)    {        n = nn;        memset(g,0,sizeof(g));        memset(flow,0,sizeof(flow));        memset(path,-1,sizeof(path));    }    void addOne(int u,int v,int yuan)    {        g[u][v] += yuan;        m += 2;     }    int bfs(int s,int t)    {        int i;        memset(path,-1,sizeof(path));        flow[s] = inf;        //如果不加这句话,bfs内部就要一共三个判断         path[s] = s;         q.push(s);        while(q.size()>0)        {            int tmp = q.front();            q.pop();            //这里i从0开始还是1开始,视情况而定             for(i=0;i<n;i++)            {                if(g[tmp][i]>0 && path[i]==-1)                {                    flow[i] = min(g[tmp][i],flow[tmp]);                    path[i] = tmp;                    q.push(i);                    if(i==t)                    {                        break;                    }                }               }            if(path[t] != -1)                break;        }        while(q.size()>0)            q.pop();        if(path[t] == -1)            return 0;        else                return flow[t];    }    int go(int s,int t)    {        int ret = 0;        while(bfs(s,t))        {            int now = path[t];            int pre = t;            ret += flow[t];            while(pre != s)            {                g[now][pre] -= flow[t];                g[pre][now] += flow[t];                pre = now;                now = path[now];            }        }        return ret;    }}edk;int vis[maxn];vector<int> g[maxn];#define pb push_backvoid dfs(int u){    for (int e=0;e<g[u].size();e++){        int v = g[u][e];        if (vis[v] == -1){            vis[v] = (vis[u] ^ 1);        }    }}int main(){    int n,m;    cin>>n>>m;    int u,v;    for (int i=0;i<m;i++){        scanf("%d%d",&u,&v);        g[u].pb(v);        g[v].pb(u);    }    memset(vis,-1,sizeof(vis));    for (int i=1;i<=n;i++){        if (vis[i] == -1){            vis[i] = 0;            dfs(i);        }           }    edk.init(n+2);          for (int i=1;i<=n;i++){        if (vis[i] == 0){            edk.addOne(0,i,1);            for (int e=0;e<g[i].size();e++){                v = g[i][e];                edk.addOne(i,v,1);            }        }        else{            edk.addOne(i,n+1,1);        }    }    cout << edk.go(0,n+1) << "\n";    return 0;}
0 0