P2055 [ZJOI2009]假期的宿舍

Posted caterpillor

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2055 [ZJOI2009]假期的宿舍相关的知识,希望对你有一定的参考价值。

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
//多组数据 的一定要注意清零 
int n,d[1005],line[1005][1005],b[1005],no[1005],vis[1005];
int s,t,kk,tot;
queue<int> q;
int bfs()
{
    memset(vis,0,sizeof vis);
    memset(d,0,sizeof d);
    while(!q.empty()) q.pop();/////////////////////
    d[s]=1;
    vis[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
//        cout<<"u:"<<u<<endl;
        q.pop();
        for(int v=1;v<=t;v++)//这个地方写成v<=n了 
        {
            if(line[u][v]>0 && !vis[v]){
                d[v]=d[u]+1;
                vis[v]=1;
                q.push(v);
                if(v==t) return 1;
            }
        }    
    }
    return 0;
}
int dinic(int u,int res)//没有优化的 
{
    if(u==t) return res;
    int sum=0; 
    for(int v=1;v<=t;v++)
    {
//        cur[u]=v;
        if(d[u]+1==d[v] && line[u][v]>0 && res>0)
        {
            int k=dinic(v,min(res,line[u][v]));
            line[u][v]-=k;
            line[v][u]+=k;
            sum+=k;
            res-=k;
            if(res==0)break;
        }
    }
    return sum;
}
int main()
{
    scanf("%d",&kk);
    while(kk--)
    {
        memset(line,0,sizeof line);
        tot=0;
        scanf("%d",&n);s=0;t=2*n+1;
        for(int i=1;i<=n;i++)
            scanf("%d",&b[i]);//1为在校学生 
        for(int i=1;i<=n;i++)
            scanf("%d",&no[i]);
        
        //前面这两个是决定超级源点到其他点的 
        int p;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&p);
                if(p==1 && b[j])
                {
                    line[i][j+n]=1;
                    line[j+n][t]=1;
                }
                if(b[i]) 
                {
                    line[i][i+n]=1;    
                    line[i+n][t]=1;
                }
            }
        for(int i=1;i<=n;i++)
        {
            if((b[i]==1 && !no[i]) || !b[i])//在校学生且不回家的+外校学生 才和源点连接 
            {
                line[0][i]=1;
                tot++;
            }
        }
        //检查连线情况 
    //    for(int i=0;i<=t;i++)
    //        for(int j=0;j<=t;j++)
    //            if(line[i][j]==1)
    //                cout<<i<<","<<j<<endl;
        //检查bfs分层情况 
    //    bfs();
    //    for(int i=0;i<=t;i++)
    //        cout<<i<<","<<d[i]<<endl;
    
    //    bfs();
    //    cout<<dinic(s,inf)<<endl; 
    //    for(int i=0;i<=t;i++)
    //        for(int j=0;j<=t;j++)
    //                cout<<i<<","<<j<<","<<line[i][j]<<endl;
    //    bfs();        
    //    cout<<dinic(s,inf)<<endl;
        int flow=0,mxflow=0; 
    //        for(int i=1;i<=t;i++)cur[i]=1; 
        while(bfs())
        {
            mxflow+=dinic(s,inf);;
        }
        if(tot==mxflow)
            cout<<"^_^"<<endl;
        else
            cout<<"T_T"<<endl;         
    }  
}

邻接表:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define inf 1e9
const int MAXN=1005;
using namespace std;
int n,s,kk,tot,hd[MAXN],t;
int b[MAXN],no[MAXN],vis[MAXN],d[MAXN];
int cnt;
struct Edge{
    int nxt,to,vl;
}edge[MAXN<<1];
void add(int u,int v,int w)
{
    cnt++;
    edge[cnt].to=v;
    edge[cnt].nxt =hd[u];
    edge[cnt].vl=w;
    hd[u]=cnt;
}
queue<int> q;
int bfs()
{
    memset(vis,0,sizeof vis);
    memset(d,0,sizeof d);
    while(!q.empty()) q.pop();
    d[s]=1;
    vis[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=hd[u];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(!vis[v] && edge[i].vl>0)
            {
                d[v]=d[u]+1;
                vis[v]=1;
                q.push(v);
                if(v==t) return 1;
            }
        }
    }
    return 0;
}
int dinic(int u,int res)
{
    if(u==t) return res;
    int sum=0;
    for(int i=hd[u];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(d[u]+1==d[v] && edge[i].vl>0 && res>0)
        {
            int k=dinic(v,min(res,edge[i].vl));
            edge[i].vl-=k;
            edge[i^1].vl+=k;
            sum+=k;
            res-=k;
            if(res==0) break;
        }
    }
    return sum;
}
int main()
{
    scanf("%d",&kk);
    while(kk--)
    {
        tot=0;s=0,t=2*n+1;
        cnt=1;memset(hd,0,sizeof hd);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&b[i]);
            if(b[i]) add(i+n,t,1),add(t,i+n,0);
        }
            
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&no[i]);
            if(!b[i] || (b[i] && !no[i]))
            {
                add(s,i,1);
                add(i,s,0);
                tot++;
            }
        }
                
        int p;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&p);
                if(p || i==j)
                {
                    add(i,j+n,1);
                    add(j+n,i,0);
                }
            }
        int mxflow=0;
        while(bfs())
        {
            mxflow+=dinic(s,inf);
        }
        if(tot==mxflow)
            cout<<"^_^"<<endl;
        else
            cout<<"T_T"<<endl;
    }
}

 

以上是关于P2055 [ZJOI2009]假期的宿舍的主要内容,如果未能解决你的问题,请参考以下文章

P2055 [ZJOI2009]假期的宿舍

P2055 [ZJOI2009]假期的宿舍(二分图&最大流)

P2055 [ZJOI2009]假期的宿舍

P2055 [ZJOI2009]假期的宿舍

P2055 [ZJOI2009]假期的宿舍 - 二分图最大匹配

bzoj 1433: [ZJOI2009]假期的宿舍