bzoj1433
1433: [ZJOI2009]假期的宿舍
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3371 Solved: 1425
[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
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。
我的方法跟网上其他博客有点不一样,随便YY的。把每个人拆成2个点ai bi,建立超级源汇S,T。
(1)S向所有 外校人员的ai建立容量1的边
(2)所有 在校的要回家的学生的bi向T连容量为1的边
(3)对于一对相互认识的人bi->aj互相建容量无穷边
(4)每个人的ai向bi建立容量1的边
这样以后一个流就表示一个挪动方案
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<cstring> #define inf 0x3f3f3f3f #define ll long long #define N 105 using namespace std; int n,S,T,tot,cur[N],st[N],hd[N],gh[N],kn[N][N],d[N],vis[N]; struct edge{int v,next,cap,flow;}e[N*N*4]; void adde(int u,int v,int c){ e[tot].v=v; e[tot].next=hd[u]; e[tot].cap=c; e[tot].flow=0; hd[u]=tot++; } bool bfs(){ queue<int>q; memset(vis,0,sizeof(vis)); q.push(S);d[S]=0; while(!q.empty()){ int u=q.front();q.pop();vis[u]=1; for(int i=hd[u];~i;i=e[i].next){ int v=e[i].v; if(e[i].cap<=e[i].flow||vis[v])continue; d[v]=d[u]+1;q.push(v); } } return vis[T]; } int dfs(int u,int a){ if(u==T||!a)return a; int fl=0,f; for(int i=hd[u];~i;i=e[i].next){ int v=e[i].v; if(d[v]==d[u]+1&&(f=dfs(v,min(e[i].cap-e[i].flow,a)))){ fl+=f;a-=f; e[i].flow+=f; e[i^1].flow-=f; if(a<=0)break; } } return fl; } int main(){ #ifdef wsy freopen("data.in","r",stdin); #else //freopen(".in","r",stdin); //freopen(".out","w",stdout); #endif int cas;scanf("%d",&cas); while(cas--){ scanf("%d",&n);S=0;T=2*n+1;tot=0; memset(hd,-1,sizeof(hd)); for(int i=1;i<=n;i++)scanf("%d",&st[i]); // for(int i=1;i<=n;i++)if(!st[i])printf("%d ",i);puts(""); for(int i=1;i<=n;i++)scanf("%d",&gh[i]); // for(int i=1;i<=n;i++)if(st[i]&&gh[i])printf("%d ",i);puts(""); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&kn[i][j]); for(int i=1;i<=n;i++){ if(st[i]){ if(gh[i])adde(i+n,T,1),adde(T,i+n,0); } else adde(S,i,1),adde(i,S,0); } for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++){ if(!kn[i][j])continue; // printf("%d %d\n",i,j); int f1=st[i],f2=st[j]; if(f1)adde(j+n,i,inf),adde(i,j+n,0); if(f2)adde(i+n,j,inf),adde(j,i+n,0); } for(int i=1;i<=n;i++) adde(i,i+n,1),adde(i+n,i,0); while(bfs()){ for(int i=S;i<=T;i++)cur[i]=hd[i]; dfs(S,0x3f3f3f3f); } int fg=0; for(int i=hd[S];~i;i=e[i].next) if(e[i].cap-e[i].flow>0)fg=1; if(fg)puts("T_T"); else puts("^_^"); } return 0; }
If you live in the echo,
your heart never beats as loud.
如果你生活在回声里,
你的心跳声永远不会轰鸣作响。