1. 程式人生 > >poj1698二分圖多重匹配

poj1698二分圖多重匹配

Alice's Chance
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 6728 Accepted: 2751

Description

Alice, a charming girl, have been dreaming of being a movie star for long. Her chances will come now, for several filmmaking companies invite her to play the chief role in their new films. Unfortunately, all these companies will start making the films at the same time, and the greedy Alice doesn't want to miss any of them!! You are asked to tell her whether she can act in all the films. 

As for a film, 
  1. it will be made ONLY on some fixed days in a week, i.e., Alice can only work for the film on these days; 
  2. Alice should work for it at least for specified number of days; 
  3. the film MUST be finished before a prearranged deadline.

For example, assuming a film can be made only on Monday, Wednesday and Saturday; Alice should work for the film at least for 4 days; and it must be finished within 3 weeks. In this case she can work for the film on Monday of the first week, on Monday and Saturday of the second week, and on Monday of the third week. 

Notice that on a single day Alice can work on at most ONE film. 

Input

The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. Each test case begins with a single line containing an integer N (1 <= N <= 20), the number of films. Each of the following n lines is in the form of "F1 F2 F3 F4 F5 F6 F7 D W". Fi (1 <= i <= 7) is 1 or 0, representing whether the film can be made on the i-th day in a week (a week starts on Sunday): 1 means that the film can be made on this day, while 0 means the opposite. Both D (1 <= D <= 50) and W (1 <= W <= 50) are integers, and Alice should go to the film for D days and the film must be finished in W weeks.

Output

For each test case print a single line, 'Yes' if Alice can attend all the films, otherwise 'No'.

Sample Input

2
2
0 1 0 1 0 1 0 9 3
0 1 1 1 0 0 0 6 4
2
0 1 0 1 0 1 0 9 4
0 1 1 1 0 0 0 6 2

Sample Output

Yes
No

Hint

A proper schedule for the first test case:



date     Sun    Mon    Tue    Wed    Thu    Fri    Sat

week1          film1  film2  film1         film1

week2          film1  film2  film1         film1

week3          film1  film2  film1         film1

week4          film2  film2  film2

Source

題意:有M部電影要拍,規定每一部電影只能在每週的某幾天拍,給定每一部電影的總拍攝日期以及截至週數,問能否拍完所有的電影,(每天只能拍一部電影)

x集是日期,y集是電影,將日期分配給有關聯的電影;

最後判斷是否能拍完只需看一下每一部電影是否被分配了足夠的日期

將電影作為Y方點,每一天作為X方點(最多50周,每週7天,所以共設350個X方點),若第i個電影可以在第j天拍就連邊(i, j)。最後判斷匹配數是否等於所有電影要拍的天數和即可

程式碼有詳細解釋:

///多重匹配
/**
  二分圖多重匹配x集合是單流量
  y集合可以多重匹配;
*/
#include<iostream>
#include<algorithm>
#include<string>
#include <string.h>
#include <stdio.h>
#include<vector>
using namespace std;
const int M = 20+10;
const int N = 350+10;
int link[M][N],vlink[M],cap[M];
bool vis[M];
vector<int> g[N];
void init()
{
    for(int i=0;i<N;i++)
        g[i].clear();
}
int path(int s)
{
    for(int it=0;it<g[s].size();it++)
    {
        int v=g[s][it];
        if(!vis[v])
        {
            vis[v]=true;
            if(vlink[v]<cap[v])///cap[v],表示y集合v點最多可以連幾條邊,
                               ///y集合每個點固定流量時,只需要該這個點就行
            {
                link[v][vlink[v]++]=s;
                return 1;
            }
            for(int j=0;j<vlink[v];j++)
            {
                if(path(link[v][j]))
                {
                    link[v][j]=s;
                    return 1;
                }
            }
        }
    }
    return 0;
}
bool max_match(int n,int m)
{
    int ans=0;
    memset(vlink,0,sizeof(vlink));
    for(int i=0;i<n;i++)///x集合,每個點只能用一次
    {
        if(g[i].size()==0)///x集合不連續,並不是n天每天都有電影可以拍攝
            continue;
        memset(vis,false,sizeof(vis));
        if(path(i))///i點可以匹配出去
            ans++;
    }
    ///ans值表示最大的匹配數
    int num=0;
    for(int i=0;i<m;i++)
    {
        ///if(vlink[i]!=cap[i])  vlink 表示多重集合流量!!!這樣也是可以的
          num+=cap[i];
        ///return false;
    }
    ///return true ;
    return ans==num;
}
int main()
{
    int T;
    int n,m,a[10],w,maxw;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&m);
        maxw=0;
        init();
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<7;j++)
                scanf("%d",&a[j]);
            scanf("%d %d",&cap[i],&w);
            maxw=max(maxw,w);
            for(int j=0;j<7;j++)
            {
                if(a[j])
                {
                    for(int k=0;k<w;k++)
                        g[k*7+j].push_back(i);
                }
            }
        }
        n=maxw*7;
        if(max_match(n,m))
            puts("Yes");
        else puts("No");
    }
    return 0;
}