1. 程式人生 > >P2055 [ZJOI2009]假期的宿舍 二分圖匹配

P2055 [ZJOI2009]假期的宿舍 二分圖匹配

using fine range 並且 復制 一個 lose 引號 數據

  

題目描述

學校放假了 · · · · · · 有些同學回家了,而有些同學則有以前的好朋友來探訪,那麽住宿就是一個問題。

比如 A 和 B 都是學校的學生,A 要回家,而 C 來看B,C 與 A 不認識。我們假設每個人只能睡和自己直接認識的人的床。那麽一個解決方案就是 B 睡 A 的床而 C 睡 B 的床。而實際情況可能非常復雜,有的人可能認識好多在校學生,在校學生之間也不一定都互相認識。

我們已知一共有 n 個人,並且知道其中每個人是不是本校學生,也知道每個本校學生是否回家。問是否存在一個方案使得所有不回家的本校學生和來看他們的其他人都有地方住。

輸入輸出格式

輸入格式:

第一行一個數 T 表示數據組數。接下來 T 組數據,每組數據第一行一個數n 表示涉及到的總人數。

接下來一行 n 個數,第 i 個數表示第 i 個人是否是在校學生 (0 表示不是,1 表示是)。再接下來一行 n 個數,第 i 個數表示第 i 個人是否回家 (0 表示不回家,1 表示回家,註意如果第 i 個人不是在校學生,那麽這個位置上的數是一個隨機的數,你應該在讀入以後忽略它)。

接下來 n 行每行 n 個數,第 i 行第 j 個數表示 i 和 j 是否認識 (1 表示認識,0 表示不認識,第 i 行 i 個的值為 0,但是顯然自己還是可以睡自己的床),認識的關系是相互的。

輸出格式:

對於每組數據,如果存在一個方案則輸出 “^_^”(不含引號) 否則輸出“T_T”(不含引號)。(註意輸出的都是半角字符,即三個符號的 ASCII 碼分別為94,84,95)

輸入輸出樣例

輸入樣例#1: 復制
1
3
1 1 0
0 1 0
0 1 1
1 0 0
1 0 0
輸出樣例#1: 復制
^_^

說明

對於 30% 的數據滿足 1 ≤ n ≤ 12。

對於 100% 的數據滿足 1 ≤ n ≤ 50,1 ≤ T ≤ 20。

多組數據!!!

人和床匹配 即可

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3
const int N=100+5;
const int M=10*N;
int n;
int mp[N][N];
struct node
{
    int school;
    int home;
}s[N];
int vis[N];
int num;
int used[N];
bool dfs(int x)
{
    for(int j=1;j<=n;j++)
    {
        if(s[j].school==0)continue;
        if(mp[x][j]&&!used[j])
        {
            used[j]=1;
            if(!vis[j]||dfs(vis[j]))
            {
                vis[j]=x;
                return 1;
            }
        }
    }
    return 0;
}

bool solve()
{
    int ans=0;
    CLR(vis,0);
    rep(i,1,n)
    {
        if(s[i].school&&s[i].home)continue;
        CLR(used,0);
        if(dfs(i))ans++;
    }

    return num==ans;
}

int main()
{
    int cas;
    RI(cas);
    while(cas--)
    {
        RI(n);
        num=0;
        rep(i,1,n)
        RI(s[i].school);
        rep(i,1,n)
        RI(s[i].home);

        rep(i,1,n)
        {
            if(s[i].school==0)num++;
            if(s[i].school&&s[i].home==0)num++;
        }
        rep(i,1,n)
        rep(j,1,n)
        RI(mp[i][j]);
        rep(i,1,n)
        mp[i][i]=1;
        if(solve())
            printf("^_^");
        else printf("T_T");
        cout<<endl;
    }
    return 0;
}
View Code

網絡流也可做

P2055 [ZJOI2009]假期的宿舍 二分圖匹配