zoukankan      html  css  js  c++  java
  • P2055 [ZJOI2009]假期的宿舍

    思路

    看到复杂的匹配条件,发现要让一个人和一个床匹配,所以就每个有床的人(指本校学生)和t连一条边,每个需要床的人(指外校的人和不回家的人)和s连一条边,i和j互相认识就把i和j的床连在一起,自己和自己的床肯定连一条边,然后流量每多1,就表示满足了一个人对床的需求,跑最大流就相当于最多能满足多少人的需求,然后如果最大流大于等于需要床的人数,就可行,否则不可行

    代码

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    using namespace std;
    const int MAXN = 1000; 
    const int INF = 0x3f3f3f3f;
    struct Edge{
        int u,v,cap,flow;
    };
    vector<Edge> edges;
    vector<int> G[MAXN];
    int cur[MAXN],s,t,n,dep[MAXN],vis[MAXN];
    void addedge(int u,int v,int cap){
        edges.push_back((Edge){u,v,cap});
        edges.push_back((Edge){v,u,0});
        int cnt=edges.size();
        G[u].push_back(cnt-2);
        G[v].push_back(cnt-1);
    }
    int dfs(int x,int a){
        if(x==t||a==0)
            return a;
        int flow=0,f=0;
        for(int &i=cur[x];i<G[x].size();i++){
            Edge &e = edges[G[x][i]];
            if(dep[e.v]==dep[x]+1&&(f=dfs(e.v,min(e.cap-e.flow,a))>0)){
                flow+=f;
                e.flow+=f;
                edges[G[x][i]^1].flow-=f;
                a-=f;
                if(!a)
                    break;
            }
        }
        return flow;
    }
    queue<int> q;
    bool bfs(void){
        memset(vis,0,sizeof(vis));
        dep[s]=0;
        q.push(s);
        vis[s]=true;
        while(!q.empty()){
            int x=q.front();
            q.pop();
            for(int i=0;i<G[x].size();i++){
                Edge &e = edges[G[x][i]];
                if(e.cap>e.flow&&(!vis[e.v])){
                    vis[e.v]=true;
                    dep[e.v]=dep[x]+1;
                    q.push(e.v);
                }
            }
        }
        return vis[t];
    }
    int dinic(void){
        int flow=0;
        while(bfs()){
            memset(cur,0,sizeof(cur));
            flow+=dfs(s,INF);
        }
        return flow;
    }
    int cnt,is_stu[MAXN],is_stay[MAXN];
    void init(void){
        cnt=0;
        edges.clear();
        for(int i=1;i<=MAXN;i++){
            G[i].clear();
        }
        memset(is_stu,false,sizeof(is_stu));
        memset(is_stay,false,sizeof(is_stay));
    }
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            init();
            s=MAXN-2;
            t=MAXN-3;
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%d",&is_stu[i]);
                if(is_stu[i])
                    addedge(i+n,t,1);
            }
            for(int i=1;i<=n;i++){
                scanf("%d",&is_stay[i]);
                if((is_stu[i]&&(!is_stay[i]))||(!is_stu[i])){
                    addedge(s,i,1);
                    ++cnt;
                }
            }
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++){
                    int x;
                    scanf("%d",&x);
                    if(i==j||x){
                        addedge(i,j+n,1);
                        continue;
                    }
                }
            if(dinic()>=cnt){
                printf("^_^
    ");
            }
            else{
                printf("T_T
    ");
            }
        }
        return 0;
    }
    
  • 相关阅读:
    系统剪切板的使用UIPasteboard
    iOS开发之GCD总结
    OC报错,after command failed: Directory not empty
    一个女孩被车多次撞到的经历
    iOS一个很好的内存检测工具
    iOS 数据库sqlite3.0操作--超简单--看我就够啦
    推送碰到的一个坑
    iOS之3DTouch的使用---很简单,看我就够啦~~
    简谈造成循环引用的原因以及处理办法
    关于拼过消息推送回调,然后跳转到指定界面
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10508956.html
Copyright © 2011-2022 走看看