bzoj 1433 假期的宿舍(网络流)

来源:互联网 发布:2017黑马python百度云 编辑:程序博客网 时间:2024/05/16 12:13

题目链接http://www.lydsy.com/JudgeOnline/problem.php?id=1433

自己看了一下网上的题解,似乎写的都是二分图,本人脑抽写网络流是因为自己这段时间想写一点网络流的题,然后上网一搜,然后这道题很巧的在名单之内,然后我就balabala的用网络流写了= =||。

建图就是以人和床位建立点,加入源点和汇点。对于每个是学校里的人的床位,与汇点T连一条容量为1的边。对于不是学校的人和是学校的人但是又不回家的人,综上即为要占据床位的人,连一条从源点S到这个人容量为的边。然后对于每两个相互认识的人,连一条由一个人到另一个人的床位的容量为1的边。注意自己要与自己的床位连边!

建好图,跑dinic,再判断是否满流即可。

#include<cstdio>#include<cstring>#include<iostream>#include<queue>using namespace std;#define inf (1e9)int S,T,N,k,tot,ans;int col[10000],a[10000],dep[10000],head[10000];struct node{int u,v,next,c;}e[100000];void adde(int u,int v,int c){e[k].u=u; e[k].v=v; e[k].c=c;e[k].next=head[u]; head[u]=k++;e[k].u=v; e[k].v=u; e[k].c=0;e[k].next=head[v]; head[v]=k++;}bool bfs(){queue<int>q;memset(dep,-1,sizeof(dep));q.push(S); dep[S]=0;while(!q.empty()){int u=q.front();q.pop();for(int i=head[u];i!=-1;i=e[i].next){int v=e[i].v;if(dep[v]==-1&&e[i].c>0){dep[v]=dep[u]+1;q.push(v);}}}return dep[T]!=-1;}int dfs(int a,int b){if(a==T)return b;int ret=0;for(int i=head[a];i!=-1;i=e[i].next){int v=e[i].v;if(dep[v]==dep[a]+1&&e[i].c>0){int x=dfs(v,min(b-ret,e[i].c));e[i].c-=x;e[i^1].c+=x;ret+=x;if(ret==b)return b;}}if(ret==0)dep[a]=-1;return ret;}void dinic(){while(bfs()){ans-=dfs(S,inf);}}void input(){int t;scanf("%d",&t);while(t--){memset(head,-1,sizeof(head));ans=0;k=0; S=0;scanf("%d",&N);T=2*N+1;for(int i=1;i<=N;i++){scanf("%d",&col[i]);if(col[i])adde(N+i,T,1);}for(int i=1;i<=N;i++){scanf("%d",&a[i]);if(!a[i] || !col[i]){adde(S,i,1); ++ans;}}for(int i=1;i<=N;i++){for(int j=1;j<=N;j++){int x;scanf("%d",&x);if(x || i==j)adde(i,j+N,1);}}dinic();if(!ans)printf("^_^\n");else printf("T_T\n");}}int main(){input();return 0;}


0 0
原创粉丝点击