您的位置:首页 > 其它

[ZJOI2009]假期的宿舍

2018-09-25 19:02 260 查看

嘟嘟嘟

 

这几天刷最大流和最小割,正好某谷推荐了这道题,就顺便AC了一下。

好水。

建立源点和汇点,对于每一个能提供床位的同学,就从源点向该同学连一条容量为1的边;对于每一个需要床位的同学,就向汇点连一条容量为1的边。因此将每一个同学拆点。

接下来考虑同学之间的关系:如果x和y互相认识,就连一条(x, y +n),(x +n, y)容量为1的边。

然后跑最大流,看总流量是否等于需要床位的人数。

1 #include<cstdio>
2 #include<iostream>
3 #include<cmath>
4 #include<algorithm>
5 #include<cstring>
6 #include<cstdlib>
7 #include<cctype>
8 #include<vector>
9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter puts("")
13 #define space putchar(' ')
14 #define Mem(a, x) memset(a, x, sizeof(a))
15 #define rg register
16 typedef long long ll;
17 typedef double db;
18 const int INF = 0x3f3f3f3f;
19 const db eps = 1e-8;
20 const int maxn = 55;
21 inline ll read()
22 {
23     ll ans = 0;
24     char ch = getchar(), last = ' ';
25     while(!isdigit(ch)) {last = ch; ch = getchar();}
26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
27     if(last == '-') ans = -ans;
28     return ans;
29 }
30 inline void write(ll x)
31 {
32     if(x < 0) x = -x, putchar('-');
33     if(x >= 10) write(x / 10);
34     putchar(x % 10 + '0');
35 }
36
37 int n, t, tot = 0;
38 bool in[maxn];
39
40 struct Edge
41 {
42     int from, to, cap, flow;
43 };
44 vector<Edge> edges;
45 vector<int> G[maxn << 1];
46 void addEdge(int from, int to)
47 {
48     edges.push_back((Edge){from, to, 1, 0});
49     edges.push_back((Edge){to, from, 0, 0});
50     int sz = edges.size();
51     G[from].push_back(sz - 2);
52     G[to].push_back(sz - 1);
53 }
54
55 int dis[maxn << 1];
56 bool bfs()
57 {
58     Mem(dis, 0); dis[0] = 1;
59     queue<int> q; q.push(0);
60     while(!q.empty())
61     {
62         int now = q.front(); q.pop();
63         for(int i = 0; i < (int)G[now].size(); ++i)
64         {
65             Edge& e = edges[G[now][i]];
66             if(!dis[e.to] && e.cap > e.flow)
67             {
68                 dis[e.to] = dis[now] + 1;
69                 q.push(e.to);
70             }
71         }
72     }
73     return dis[t];
74 }
75 int cur[maxn << 1];
76 int dfs(int now, int res)
77 {
78     if(now == t || res == 0) return res;
79     int flow = 0, f;
80     for(int& i = cur[now]; i < (int)G[now].size(); ++i)
81     {
82         Edge& e = edges[G[now][i]];
83         if(dis[e.to] == dis[now] + 1 && (f = dfs(e.to, min(res, e.cap - e.flow))) > 0)
84         {
85             e.flow += f;
86             edges[G[now][i] ^ 1].flow -= f;
87             flow += f; res -= f;
88             if(res == 0) break;
89         }
90     }
91     return flow;
92 }
93
94 int maxflow()
95 {
96     int flow = 0;
97     while(bfs())
98     {
99         Mem(cur, 0);
100         flow += dfs(0, INF);
101     }
102     return flow;
103 }
104
105 void init(int n)
106 {
107     edges.clear();
108     for(int i = 0; i <= n; ++i) G[i].clear();
109     Mem(in, 0);
110     tot = 0;
111 }
112
113 int main()
114 {
115     int T = read();
116     while(T--)
117     {
118         n = read(); t = (n << 1) + 1;
119         init(t);
120         for(int i = 1; i <= n; ++i)
121         {
122             in[i] = (bool)read();
123             if(in[i]) addEdge(0, i);
124             else addEdge(i + n, t), tot++;
125         }
126         for(int i = 1; i <= n; ++i)
127         {
128             int x = read();
129             if(in[i] && !x) addEdge(i + n, t), tot++;
130         }
131         for(int i = 1; i <= n; ++i)
132             for(int j = 1; j <= n; ++j)
133             {
134                 int x = read();
135                 if(x || i == j) addEdge(i, j + n), addEdge(j, i + n);
136             }
137         printf("%s\n", maxflow() == tot ? "^_^" : "T_T");
138     }
139     return 0;
140 }
View Code

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: