题目
https://www.luogu.org/problemnew/show/P2055#sub
在学校,到了假期,就有部分学生要回家,有部分非本校学生要看望剩下的学生,根据他们是否认识,来分配他们的床位(床位一定)
解题思路
可以用匈牙利算法来做(应该能过), 如果用Dinic算法做的话,【重点在建图:把空余的床位连接源点,把剩下的学生连接汇点,然后将这两堆东西连接在一起。】,套模板。
代码
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int inf=100000000;
queue<int>que;
struct node{
int x,y,c,next;
}a[200001];
int n,s,t,ans,len=0,last[200001],dis[200001],b[200001];
int read()
{
int f=0,p=1; char c;
while(c=getchar(),c<=47||c>=58) if(c=='-') p=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),c>=48&&c<=57) f=(f<<3)+(f<<1)+c-48;
return p*f;
}
int minn(int xa,int ya)
{return xa>ya?ya:xa;}
void add(int xa,int ya,int ca)
{
a[++len].y=ya; a[len].c=ca; a[len].next=last[xa]; last[xa]=len;
a[++len].y=xa; a[len].c=0; a[len].next=last[ya]; last[ya]=len;
}
bool bfs()
{
memset(dis,-1,sizeof(dis));
while (!que.empty()) que.pop();
que.push(s); dis[s]=0;
while(!que.empty())
{
int u=que.front(); que.pop();
for (int i=last[u];~i;i=a[i].next)
if (a[i].c&&dis[a[i].y]==-1)
{
dis[a[i].y]=dis[u]+1;
if (a[i].y==t) return 1;
que.push(a[i].y);
}
}
return 0;
}
int dfs(int xq,int maxf)
{
if (xq==t||!maxf) return maxf;
int ret=0;
for (int i=last[xq];~i;i=a[i].next)
if (a[i].c&&dis[a[i].y]==dis[xq]+1)
{
int f=dfs(a[i].y,minn(a[i].c,maxf-ret));
a[i].c-=f;
a[i^1].c+=f;
ret+=f;
if (maxf==ret) break;
}
if (!ret) dis[xq]=-1;
return ret;
}
int dinic()
{
int anss=0;
while (bfs()) anss+=dfs(s,inf);
return anss;
}
int main()
{
int k; k=read();
for (int kk=1;kk<=k;kk++)
{
len=-1;ans=0;
memset(last,-1,sizeof(last));
n=read();
s=0; t=n<<1|1;
for (int i=1;i<=n;i++)
{
b[i]=read();
if (b[i]) add(i+n,t,1);
}
int q;
for (int i=1;i<=n;i++)
{
q=read();
if (!b[i]||(b[i]&&!q))
{
add(s,i,1);
ans++;
}
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
q=read();
if (i==j||q) add(i,j+n,1);
}
if (dinic()==ans) printf("^_^\n"); else printf("T_T\n");
}
}