[ZJOI2009]假期的宿舍

OJ题号:

洛谷2055、BZOJ1433

思路:

将需要住宿的学生与超极源点$S$连一条边,将所有的床与超极汇点$T$连一条边。
将每个人与可以睡的床连一条边。
最大流跑二分图最大匹配即可。
连边时注意细节。

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<vector>
 5 #include<cstring>
 6 inline int getint() {
 7     char ch;
 8     while(!isdigit(ch=getchar()));
 9     int x=ch^'0';
10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
11     return x;
12 }
13 const int inf=0x7fffffff;
14 int s,t;
15 struct Edge {
16     int from,to;
17     bool remain;
18 };
19 const int E=5200,V=202;
20 Edge e[E];
21 std::vector<int> g[V];
22 int sz;
23 inline void add_edge(const int u,const int v,const bool w) {
24     e[sz]=(Edge){u,v,w};
25     g[u].push_back(sz);
26     sz++;
27 }
28 int p[V];
29 bool a[V];
30 inline bool Augment() {
31     memset(a,0,sizeof a);
32     a[s]=inf;
33     std::queue<int> q;
34     q.push(s);
35     while(!q.empty()&&!a[t]) {
36         int x=q.front();
37         q.pop();
38         for(unsigned i=0;i<g[x].size();i++) {
39             Edge &y=e[g[x][i]];
40             if(!a[y.to]&&y.remain) {
41                 p[y.to]=g[x][i];
42                 a[y.to]=a[x]&&y.remain;
43                 q.push(y.to);
44             }
45         }
46     }
47     return a[t];
48 }
49 inline int EdmondsKarp() {
50     int maxflow=0;
51     while(Augment()) {
52         for(int i=t;i!=s;i=e[p[i]].from) {
53             e[p[i]].remain^=true;
54             e[p[i]^1].remain^=true;
55         }
56         maxflow++;
57     }
58     return maxflow;
59 }
60 inline void reset() {
61     sz=0;
62     for(int i=0;i<V;i++) {
63         g[i].clear();
64     }
65 }
66 int main() {
67     for(int T=getint();T;T--) {
68         reset();
69         int n=getint();
70         s=0,t=n<<1|1;
71         bool isStudent[n+1];
72         for(int i=1;i<=n;i++) {
73             if(isStudent[i]=(bool)getint()) {
74                 add_edge(n+i,t,true);
75                 add_edge(t,n+i,false);
76             }
77         }
78         int cnt=0;
79         for(int i=1;i<=n;i++) {
80             if(!getint()||!isStudent[i]) {
81                 add_edge(s,i,true);
82                 add_edge(i,s,false);
83                 cnt++;
84             }
85         }
86         for(int i=1;i<=n;i++) {
87             for(int j=1;j<=n;j++) {
88                 if(getint()||(i==j)) {
89                     add_edge(i,n+j,true);
90                     add_edge(n+j,i,false);
91                 }
92             }
93         }
94         puts(EdmondsKarp()==cnt?"^_^":"T_T");
95     }
96     return 0;
97 }

 

posted @ 2017-07-29 20:06  skylee03  阅读(126)  评论(0编辑  收藏  举报