您的位置:首页 > 其它

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

2015-12-20 16:10 423 查看

1433: [ZJOI2009]假期的宿舍

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 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 ≤ 50,1 ≤ T ≤ 20。

Source

【思路】

最大流。

构图:

1
每个人建立两个点u1,u2,建立s t点。

2
如果需要床则s向u1连边,如果有床u2向t连边,如果认识u1向v2连边。

Ps:总而言之,建图的思路就是要分配已有的床给需要床的人。

【代码】

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#define FOR(a,b,c) for(int a=(b);a<(c);a++)
using namespace std;

const int maxn = 500+10;
const int INF = 1e9;

struct Edge{
int u,v,cap,flow;
};
struct Dinic {
int n,m,s,t;
bool vis[maxn];
int d[maxn],cur[maxn];
vector<int> G[maxn];
vector<Edge> es;

void init(int n) {
this->n=n;
es.clear();
for(int i=0;i<n;i++) G[i].clear();
}
void AddEdge(int u,int v,int cap) {
es.push_back((Edge){u,v,cap,0});
es.push_back((Edge){v,u,0,0});
m=es.size();
G[u].push_back(m-2);
G[v].push_back(m-1);
}

bool BFS() {
queue<int> q;
memset(vis,0,sizeof(vis));
q.push(s); vis[s]=1; d[s]=0;
while(!q.empty()) {
int u=q.front(); q.pop();
for(int i=0;i<G[u].size();i++) {
Edge& e=es[G[u][i]];
int v=e.v;
if(!vis[v] && e.cap>e.flow) {
vis[v]=1;
d[v]=d[u]+1;
q.push(v);
}
}
}
return vis[t];
}
int DFS(int u,int a) {
if(u==t || a==0) return a;
int flow=0,f;
for(int& i=cur[u];i<G[u].size();i++){
Edge& e=es[G[u][i]];
int v=e.v;
if( d[v]==d[u]+1 && (f=DFS(v,min(a,e.cap-e.flow)))>0 ) {
e.flow+=f;
es[G[u][i]^1].flow-=f;
flow+=f,a-=f;
if(!a) break;
}
}
return flow;
}
int Maxflow(int s,int t) {
this->s=s , this->t=t;
int flow=0;
while(BFS()) {
memset(cur,0,sizeof(cur));
flow+=DFS(s,INF);
}
return flow;
}
} dc;

int n,m;
int f[maxn];

int main() {
int T;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
dc.init(n*2+2);
int s=n*2,t=s+1;
FOR(i,0,n) {
scanf("%d",&f[i]);
if(f[i]) dc.AddEdge(i+n,t,1);
}
int x,sum=0;
FOR(i,0,n) {
scanf("%d",&x);
if((f[i]&&!x) || (!f[i])) {
dc.AddEdge(s,i,1);
sum++;
}
}
FOR(i,0,n) FOR(j,0,n) {
scanf("%d",&x);
if(x || i==j) dc.AddEdge(i,j+n,1);
}
int flow=dc.Maxflow(s,t);
if(flow==sum) printf("^_^\n");
else printf("T_T\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: