zoukankan      html  css  js  c++  java
  • SSLZYC 洛谷P2055 假期的宿舍

    题目大意:
    这里写图片描述


    思路:

    网络流最大流

    建图:
    1.学生编号为1m,床编号为m+12m
    2.将在校学生(无论是否回家)与自己的床相连,边权为1。
    3.将在校学生(无论是否回家)的床与结束点T相连,边权为1。
    4.将不回家的学生和来看望的外校同学与起始点S相连,边权为1。
    5.将读入的两两认识的人相连,边权为1。

    举个栗子(样例):
    这里写图片描述

    第一步:
    这里写图片描述
    第二步:
    这里写图片描述
    第三步:
    这里写图片描述
    第四步:
    这里写图片描述
    第五步:
    这里写图片描述
    然后就建好图啦!
    然后就可以找增广路再AC啦!2333


    代码:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    const int inf=999999999;
    int k,m,n,x,b[201],c[201][201],f[201][201],t,s,d,sum,tot;
    
    struct N
    {
        int zx,ls;  //分别表示是否在校和是否留宿
    }p[201];
    
    int dfs(int x)  //找增广路
    {
        if (x==t) return 1;  //到达了结束点,即找到了一条增广路
        for (int i=0;i<=t;i++)  //枚举每个点
         if (b[i]==-1&&(f[i][x]>0||c[x][i]-f[x][i]>0))
         {
            b[i]=x;
            if (dfs(i)==1) return 1;
         }
        return 0;
    }
    
    void addflow()
    {
        int i;
        d=inf;
        i=t;
        while (i!=s)  //找最小边权
        {
            if (c[b[i]][i]>0) d=min(d,c[b[i]][i]-f[b[i]][i]);
            if (c[i][b[i]]>0) d=min(d,f[i][b[i]]);
            i=b[i];
        }
        i=t;
        while (i!=s)  //减去最小边权
        {
            if (c[b[i]][i]>0) f[b[i]][i]+=d;
            if (c[i][b[i]]>0) f[i][b[i]]-=d;
            i=b[i];
        }
        sum+=d;  
        return;
    }
    
    int main()
    {
        scanf("%d",&k);  //多组数据
        for (int ___=1;___<=k;___++)
        {
            memset(b,0,sizeof(b));
            memset(c,0,sizeof(c));
            memset(f,0,sizeof(f));
            memset(p,0,sizeof(p));  
            sum=0;
            tot=0;  //初始化
            scanf("%d",&m);
            n=m*2;
            s=0;
            t=n+1;  //初始化+建图第一步
            for (int i=s;i<=t;i++) 
              b[i]=-1;  //依旧是初始化
            for (int i=1;i<=m;i++)  
            {
                scanf("%d",&p[i].zx);
                if (p[i].zx==1)  //在校
                {
                    c[i][i+m]=1;  //第二步
                    c[i+m][t]=1;  //第三步
                }
            }
            b[s]=0;
            for (int i=1;i<=m;i++)
            {
                scanf("%d",&p[i].ls);
                if (p[i].ls==0||p[i].zx==0)  //留宿或看望
                {
                    tot++;
                    c[s][i]=1;  //第四步
                }
            }
            for (int i=1;i<=m;i++)
             for (int j=1;j<=m;j++)  
             {
                scanf("%d",&x);
                if (x==1&&p[j].zx==1)  //互相认识  
                {
                    c[i][j+m]=1;  //第五步
                }
             }  
            while (dfs(s)==1)  //找增广路
            {
                addflow();  //减去边权
                for (int i=s;i<=t;i++)
                  b[i]=-1;
                b[s]=0;  //重新初始化
            }
            if (sum>=tot) puts("^_^");  
              else puts("T_T");
        }
        return 0;
    }
  • 相关阅读:
    ORA-01536: 超出表空间 'tablespace_name' 的空间限额
    Oracle数据库表索引失效,解决办法:修改Oracle数据库优化器模式
    解决response.setHeader("Content-disposition" 中文乱码问题
    MyBatis配置:在控制台打印SQL语句
    JS 字符串转日期格式 日期格式化字符串
    远程桌面管理工具Remote Desktop Connection Manager
    调整Windows操作系统下时间同步的频率
    Oracle数据库中字符型字段按数字排序
    “Error:(1, 1) java: 非法字符: 'ufeff'”错误解决办法
    本次孩子流感总结
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/9313058.html
Copyright © 2011-2022 走看看