bzoj1433_最大流|二分图最大匹配

来源:互联网 发布:88端口怎么起 编辑:程序博客网 时间:2024/05/16 05:34

调了一下午的网络流, 最后发现是因为想要用0作为下标而遍历的时候还是用习惯性的写法, 简直不开心。

网络流的题目基本都是重点在建模上, 我们来看看这一题怎么建模: 首先, 学生人数和可用床数是确定的, 我们就自己创造一个源点和一个汇点。 考虑到学生必须全部有床睡, 那么从原点出发流到床再流到学生即可。 这时我们能够机智的发现一件事, 其实就是求一个二分图的最大匹配, 愤愤然地感觉自己被坑了。 最终只要看匹配数是否等于有需求的学生数即可。

另一件事就是判断有需求的学生, 只要是外来的或校内但不回家的就是有需求的。

#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#include <cstdlib>#define N 200#define M 20000#define INF 10000000using namespace std;struct edge{    int to, next;}e[M];int t, n, num, ans, cont;int a[N], b[N], p[N], mat[N], flag[N];void add(int x, int y){    e[num].to = y;    e[num].next = p[x];    p[x] = num++;}void clean(){    ans = num = cont = 0;    memset(p, -1, sizeof p);    memset(e, 0, sizeof e);    memset(mat, 0, sizeof mat);}void init(){    clean();    int x;    scanf("%d", &n);    t = n << 1 | 1;    for (int i = 1; i <= n; ++i)    scanf("%d", &a[i]);    for (int i = 1; i <= n; ++i)    scanf("%d", &b[i]);    for (int i = 1; i <= n; ++i)    if (!a[i] || (a[i] && !b[i])) ++cont;    for (int i = 1; i <= n; ++i)    for (int j = 1; j <= n; ++j)    {        scanf("%d", &x);        if (((i == j && a[i]) || (x && a[j])) && (!a[i] || (a[i] && !b[i])))        {            add(j+n, i);            add(i, j+n);        }    }}bool find(int x){    for (int i = p[x]; i != -1; i = e[i].next)    {        int k = e[i].to;        if (!flag[k])        {            flag[k] = 1;            if (!mat[k] || find(mat[k]))            {                mat[k] = x;                return true;            }        }    }    return false;}void deal(){    for (int i = 1; i <= n; ++i)    {        memset(flag, 0, sizeof flag);        ans += find(i);    }    if (ans == cont) printf("^_^\n");    else printf("T_T\n");}int main(){    freopen("a.in", "r", stdin);    int T;    scanf("%d", &T);    while(T--)    {        init();        deal();    }    return 0;}//二分图匹配代码

#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#include <cstdlib>#define N 200#define M 20000#define INF 10000000using namespace std;struct edge{    int to, next, cap, flow;}e[M];int t, n, num, ans, cont;int a[N], b[N], p[N], d[N], flag[N], now[N];void add(int x, int y, int z){    e[num].to = y;    e[num].next = p[x];    e[num].cap = z;    p[x] = num++;}void clean(){    ans = num = cont = 0;    memset(p, -1, sizeof p);    memset(d, 0, sizeof d);    memset(e, 0, sizeof e);}void init(){    clean();    int x;    scanf("%d", &n);    t = n << 1 | 1;    for (int i = 1; i <= n; ++i)    scanf("%d", &a[i]);    for (int i = 1; i <= n; ++i)    scanf("%d", &b[i]);    for (int i = 1; i <= n; ++i)    if (!a[i] || (a[i] && !b[i]))    {        add(i, t, 1);        add(t, i, 0);        ++cont;    }    for (int i = 1; i <= n; ++i)    for (int j = 1; j <= n; ++j)    {        scanf("%d", &x);        if (((i == j && a[i]) || (x && a[j])) && (!a[i] || (a[i] && !b[i])))        {            add(j+n, i, 1);            add(i, j+n, 0);        }    }    for (int i = 1; i <= n; ++i)    if (a[i])    {        add(0, i+n, 1);        add(i+n, 0, 0);    }}bool bfs(){    memset(flag, 0, sizeof flag);    d[0] = 0, flag[0] = 1;    queue<int>q;    q.push(0);    while(!q.empty())    {        int x = q.front();        q.pop();        for (int i = p[x]; i != -1; i = e[i].next)        {            int k = e[i].to;            if (!flag[k] && e[i].cap > e[i].flow)            {                flag[k] = 1;                d[k] = d[x] + 1;                q.push(k);            }        }    }    for (int i = 0; i <= t; ++i) now[i] = p[i];    return flag[t];}int dfs(int x, int mini){    if (x == t || !mini) return mini;    int flow = 0;    for (int i = now[x]; i != -1; i = e[i].next)    {        now[x] = i;        int k = e[i].to;        if (d[k] == d[x] + 1)        {            int tmp = dfs(k, min(mini, e[i].cap-e[i].flow));            if (tmp <= 0) continue;            e[i].flow += tmp;            e[i^1].flow -= tmp;            flow += tmp;            mini -= tmp;            if (!mini) break;        }    }    return flow;}void deal(){    while(bfs()) ans += dfs(0, INF);    if (ans == cont) printf("^_^\n");    else printf("T_T\n");}int main(){    freopen("a.in", "r", stdin);    freopen("a.out", "w", stdout);    int T;    scanf("%d", &T);    while(T--)    {        init();        deal();    }    return 0;}//网络流代码



0 0
原创粉丝点击