1. 程式人生 > >P2055 [ZJOI2009]假期的宿舍

P2055 [ZJOI2009]假期的宿舍

結果 代碼 不知道 next 宿舍 pre strong turn 不一定

有點燒腦。。。


這道題是求二分圖完美匹配。沒看請題意還不知道是求完美匹配,結果爆零。

人一共分三種:

  1. 在校學生 && 回家。這類人擁有一個床,但是不睡。

  2. 在校學生 && 不回家。這類人擁有一個床,但也要睡一個床。有時不一定睡自己的。

  3. 外來學生。這類人沒床卻想睡覺。

顯然要用\(2n\)的空間來建立人和床。

等待匹配的人只有1、3兩種情況,等待匹配的床只有1、2兩種情況。

第1種情況連床沒什麽卵用。又不睡。

只有第2種情況的人可以連自己的床。

第3種情況的人一定要睡別人的床。

在2、3種情況中,只要認識的人有床,就可以連接

然後套個二分圖匹配的樣子,跑跑網絡流就ok了。

最後判斷答案是不是等於人數,輸出那兩個表情即可。

代碼:

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
const int maxn = 1005, INF = 19260817;
struct Edges
{
    int next, to, weight;
} e[1000005];
int head[maxn], tot;// remember to set tot = 1
int n, s, t;
bool in_school[maxn], go_home[maxn];
int dep[maxn], cur[maxn];
void link(int u, int v, int w)
{
    e[++tot] = (Edges){head[u], v, w};
    head[u] = tot;
}
void addEdges(int u, int v, int w)
{
    link(u, v, w); link(v, u, 0);
}
int read()
{
    int ans = 0; char ch = getchar();
    while(ch > ‘9‘ || ch < ‘0‘) ch = getchar();
    while(ch >= ‘0‘ && ch <= ‘9‘)
    {
        ans = ans * 10 + ch - ‘0‘;
        ch = getchar();
    }
    return ans;
}
bool bfs()
{
    memset(dep, 0, sizeof(dep));
    std::queue<int> q;
    dep[s] = 1; q.push(s);
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        for(int i = head[u]; i; i = e[i].next)
        {
            int v = e[i].to;
            if(!dep[v] && e[i].weight > 0)
            {
                dep[v] = dep[u] + 1;
                q.push(v);
            }
        }
    }
    return dep[t];
}
int dfs(int u, int flow)
{
    if(u == t) return flow;
    for(int &i = cur[u]; i; i = e[i].next)
    {
        int v = e[i].to;
        if(dep[v] == dep[u] + 1 && e[i].weight > 0)
        {
            int di = dfs(v, std::min(e[i].weight, flow));
            if(di > 0)
            {
                e[i].weight -= di;
                e[i ^ 1].weight += di;
                return di;
            }
        }
    }
    return 0;
}
int dinic()
{
    int ans = 0;
    while(bfs())
    {
        for(int i = 1; i <= t; i++) cur[i] = head[i];
        while(int temp = dfs(s, INF)) ans += temp;
    }
    return ans;
}
int main()
{
    int T = read();
    while(T--)
    {
        // how to define nodes?
        // [1, n] person
        // [n + 1, n + n] beds
        // not go home->need bed
        // only do in-school students have beds
        // not in-school students->the persons visiting
        // go home->never consider them
        tot = 1; memset(head, 0, sizeof(head)); memset(e, 0, sizeof(e));
        n = read();
        int cnt = 0;
        s = n + n + 1; t = s + 1;
        for(int i = 1; i <= n; i++) in_school[i] = read();
        for(int i = 1; i <= n; i++) go_home[i] = read();
        for(int i = 1; i <= n; i++)
        {
            addEdges(s, i, 1);
            addEdges(n + i, t, 1);
            if((in_school[i] && !go_home[i]) || !in_school[i]) cnt++;
        }
        for(int i = 1; i <= n; i++)
        {
            if(in_school[i] && !go_home[i]) addEdges(i, n + i, 1);
            for(int j = 1; j <= n; j++)
            {
                int temp = read();
                if(temp && in_school[j] && !(in_school[i] && go_home[i])) addEdges(i, n + j, 1);
            }
        }
        int ans = dinic();
        if(ans == cnt) printf("^_^\n");
        else printf("T_T\n");
    }
    return 0;
}

P2055 [ZJOI2009]假期的宿舍