【最大流,dinic】P2055 [ZJOI2009]假期的宿舍

  1 #include<iostream>
  2 #include<queue>
  3 #include<cstring>
  4 using namespace std;
  5
  6 const int maxn = 60;
  7
  8 const int INF = 0x3f3f3f3f;
  9 int n;
 10 int head[maxn << 2 | 1];
 11 int cnt;
 12 int d[maxn << 2 | 1];
 13 int now[maxn << 2 | 1];
 14 int school[maxn];
 15 int home[maxn];
 16 int st, ed;
 17
 18 struct Edge
 19 {
 20     int v, nxt, w;
 21 }e[maxn << 4 | 1];
 22
 23 void add_dinic(int u, int v)
 24 {
 25     e[++cnt].v = v;
 26     e[cnt].w = 0;
 27     e[cnt].nxt = head[u];
 28     head[u] = cnt;
 29 }
 30
 31 inline void add(int u, int v, int w)
 32 {
 33     e[++cnt].v = v;
 34     e[cnt].w = w;
 35     e[cnt].nxt = head[u];
 36     head[u] = cnt;
 37     add_dinic(v, u);
 38 }
 39
 40 int dfs_dinic(int x, int flow)
 41 {
 42     if (x == ed) return flow;
 43     int res = 0;
 44     for (int i = now[x]; i != -1; i = e[i].nxt)
 45     {
 46         int v = e[i].v;
 47         if (d[v] + 1 == d[x] && e[i].w > 0)
 48         {
 49             int k = dfs_dinic(v, min(e[i].w, flow));
 50             res += k;
 51             flow -= k;
 52             e[i].w -= k;
 53             e[i ^ 1].w += k;
 54             if (!flow) break;
 55         }
 56     }
 57     return res;
 58 }
 59
 60 bool bfs_dinic()
 61 {
 62     memset(d, 0, sizeof(d));
 63     queue<int>q;
 64     q.push(ed);
 65     d[ed] = 1;
 66     while (!q.empty())
 67     {
 68         int u = q.front();
 69         q.pop();
 70         for (int i = head[u]; i != -1; i = e[i].nxt)
 71         {
 72             int v = e[i].v;
 73             if (!d[v] && e[i ^ 1].w > 0)
 74             {
 75                 q.push(v);
 76                 d[v] = d[u] + 1;
 77             }
 78         }
 79     }
 80     return d[st] > 0;
 81 }
 82
 83
 84 int dinic()
 85 {
 86     int flow = 0;
 87     while (bfs_dinic())
 88     {
 89         for (int i = 0; i <= ed; i++) now[i] = head[i];
 90         flow += dfs_dinic(st, INF);
 91     }
 92     return flow;
 93 }
 94
 95 int main()
 96 {
 97     int T;
 98     cin >> T;
 99     while (T--)
100     {
101         memset(head, -1, sizeof(head));
102         cnt = 1;
103         //源点0,汇点2n+1
104         cin >> n;
105         int tot = 0;
106         st = 0;
107         ed = n << 1 | 1;
108         for (int i = 1; i <= n; i++)
109         {
110             cin >> school[i];
111             if(school[i]) add(i + n, ed, 1);
112         }
113         for (int i = 1; i <= n; i++)
114         {
115                 cin >> home[i];
116                 if ((!home[i] && school[i]) || !school[i]) add(st, i, 1), tot++;
117         }
118         for (int i = 1; i <= n; i++)
119         {
120             for (int j = 1; j <= n; j++)
121             {
122                 int t;
123                 cin >> t;
124                 if (t || i == j) add(i, j + n, 1);
125             }
126         }
127         int ans = 0;
128         ans = dinic();
129         if (ans >= tot) cout << "^_^" << endl;
130         else cout << "T_T" << endl;
131         memset(now, 0, sizeof(now));
132     }
133 }

原文地址:https://www.cnblogs.com/thjkhdf12/p/11823724.html

时间: 2024-08-29 23:03:55

【最大流,dinic】P2055 [ZJOI2009]假期的宿舍的相关文章

luogu P2055 [ZJOI2009]假期的宿舍

二次联通门 : luogu P2055 [ZJOI2009]假期的宿舍 /* luogu P2055 [ZJOI2009]假期的宿舍 建图时分为两个集合 床一个集合 人一个集合 S到床连边 人与自己认识的人连边 人与T点连边 然后跑最大流判断即可 */ #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <queue> #de

P2055 [ZJOI2009]假期的宿舍

题目描述 学校放假了 · · · · · · 有些同学回家了,而有些同学则有以前的好朋友来探访,那么住宿就是一个问题.比如 A 和 B 都是学校的学生,A 要回家,而 C 来看B,C 与 A 不认识.我们假设每个人只能睡和自己直接认识的人的床.那么一个解决方案就是 B 睡 A 的床而 C 睡 B 的床.而实际情况可能非常复杂,有的人可能认识好多在校学生,在校学生之间也不一定都互相认识.我们已知一共有 n 个人,并且知道其中每个人是不是本校学生,也知道每个本校学生是否回家.问是否存在一个方案使得所

P2055 [ZJOI2009]假期的宿舍 - 二分图最大匹配

把人和床分开考虑,题目说每个人只能睡和自己直接认识的人的床,就是一种边的关系,但是并不是人与人,实际上人与人之间连边是很难处理的,但是如果把人和床连边,就是一张二分图,左右两边分别是不同的东西,然后求一下最大匹配就好了 没思路的时候换换角度,看能不能搞出什么"新东西"来 注意多组数据不超时的情况下能用memset尽量用,有时候感觉某个数组可以不清空但实际上是需要清空的 还有注意连边的时候没那么简单...看注释吧 #include <algorithm> #include &

bzoj1433 [ZJOI2009]假期的宿舍(最大流)

1433: [ZJOI2009]假期的宿舍 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1717  Solved: 754[Submit][Status][Discuss] Description Input Output Sample Input 1 3 1 1 0 0 1 0 0 1 1 1 0 0 1 0 0 Sample Output ˆ ˆ HINT 对于30% 的数据满足1 ≤ n ≤ 12. 对于100% 的数据满足1 ≤ n ≤

bzoj 1433: [ZJOI2009]假期的宿舍 -- 最大流

1433: [ZJOI2009]假期的宿舍 Time Limit: 10 Sec  Memory Limit: 162 MB Description Input Output Sample Input 1 3 1 1 0 0 1 0 0 1 1 1 0 0 1 0 0 Sample Output ˆ ˆ HINT 对于30% 的数据满足1 ≤ n ≤ 12.对于100% 的数据满足1 ≤ n ≤ 50,1 ≤ T ≤ 20. 我们从源点向所有住宿的人连边,从所有的床位连向汇点,然后再从人连向他所

bzoj1433 [ZJOI2009]假期的宿舍 最大流

[ZJOI2009]假期的宿舍 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3429  Solved: 1459[Submit][Status][Discuss] Description Input Output Sample Input 1 3 1 1 0 0 1 0 0 1 1 1 0 0 1 0 0 Sample Output ˆ ˆ HINT 对于30% 的数据满足1 ≤ n ≤ 12. 对于100% 的数据满足1 ≤ n ≤ 50,1

[BZOJ1433][luogu_P2055][ZJOI2009]假期的宿舍

[BZOJ1433][luogu_P2055][ZJOI2009]假期的宿舍 试题描述 输入 输出 输入示例 1 3 1 1 0 0 1 0 0 1 1 1 0 0 1 0 0 输出示例 ^_^ 数据规模及约定 对于 \(30\texttt{%}\) 的数据满足 \(1 \le n \le 12\). 对于 \(100\texttt{%}\) 的数据满足 \(1 \le n \le 50,1 \le T \le 20\). 题解 每个人和每个人的床分别建一个节点,源点向不回家的和不是学生的人连边

[ZJOI2009]假期的宿舍

1433: [ZJOI2009]假期的宿舍 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2870  Solved: 1213[Submit][Status][Discuss] Description Input Output Sample Input 1 3 1 1 0 0 1 0 0 1 1 1 0 0 1 0 0 Sample Output ˆ ˆ HINT 对于30% 的数据满足1 ≤ n ≤ 12.对于100% 的数据满足1 ≤ n ≤

bzoj1433:[ZJOI2009]假期的宿舍

明显的二分图最大匹配. #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #include<bitset> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c