二分匹配,匈牙利算法

POJ - 1274 

Farmer John completed his new barn just last week, complete with all the latest milking technology. Unfortunately, due to engineering problems, all the stalls in the new barn are different. For the first week, Farmer John randomly assigned cows to stalls, but it quickly became clear that any given cow was only willing to produce milk in certain stalls. For the last week, Farmer John has been collecting data on which cows are willing to produce milk in which stalls. A stall may be only assigned to one cow, and, of course, a cow may be only assigned to one stall. 
Given the preferences of the cows, compute the maximum number of milk-producing assignments of cows to stalls that is possible. 
Input
The input includes several cases. For each case, the first line contains two integers, N (0 <= N <= 200) and M (0 <= M <= 200). N is the number of cows that Farmer John has and M is the number of stalls in the new barn. Each of the following N lines corresponds to a single cow. The first integer (Si) on the line is the number of stalls that the cow is willing to produce milk in (0 <= Si <= M). The subsequent Si integers on that line are the stalls in which that cow is willing to produce milk. The stall numbers will be integers in the range (1..M), and no stall will be listed twice for a given cow.
Output
For each case, output a single line with a single integer, the maximum number of milk-producing stall assignments that can be made.
Sample Input
5 5
2 2 5
3 2 3 4
2 1 5
3 1 2 5
1 2 
Sample Output
4
题意:N只牛。 每只牛对某个位置有偏好。 等于说是相匹配。  问最大有多少只牛是匹配的。  等于问的最大匹配数。

#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<vector>
#include<map>
#include<set>
using namespace std;


#define LL long long
#define INF 1E4 * 1E9
#define pi acos(-1)
#define endl '\n'
#define me(x) memset(x,0,sizeof(x));
const int maxn=1e3+5;
const int maxx=1e6+5;

int mapp[maxn][maxn],vis[maxn],link[maxn];
int i,n,m,a,k,cnt;
int dfs(int x)
{
    int i;
    for(i=1; i<=n; i++)
    {
        if(!vis[i] && mapp[x][i])
        {
            vis[i]=1;
            if(link[i]==0 || dfs(link[i]))
            {
                link[i]=x;
                return 1;
            }
        }
    }
    return 0;
}
void Hungary()
{
    cnt=0;
    for(i=1; i<=n; i++)
    {
        me(vis);
        if(dfs(i))
        {
            cnt++;
        }
    }
}
int main()
{
    while(cin>>n>>m){
    me(mapp); me(link);
    for(i=1; i<=n; i++)
    {
        cin>>k;
        for(int j=1; j<=k; j++)
        {
            cin>>a;
            mapp[i][a]=1;
        }
    }
    Hungary();
    cout<<cnt<<endl;
    }
}

POJ - 3020 

The Global Aerial Research Centre has been allotted the task of building the fifth generation of mobile phone nets in Sweden. The most striking reason why they got the job, is their discovery of a new, highly noise resistant, antenna. It is called 4DAir, and comes in four types. Each type can only transmit and receive signals in a direction aligned with a (slightly skewed) latitudinal and longitudinal grid, because of the interacting electromagnetic field of the earth. The four types correspond to antennas operating in the directions north, west, south, and east, respectively. Below is an example picture of places of interest, depicted by twelve small rings, and nine 4DAir antennas depicted by ellipses covering them. 
 
Obviously, it is desirable to use as few antennas as possible, but still provide coverage for each place of interest. We model the problem as follows: Let A be a rectangular matrix describing the surface of Sweden, where an entry of A either is a point of interest, which must be covered by at least one antenna, or empty space. Antennas can only be positioned at an entry in A. When an antenna is placed at row r and column c, this entry is considered covered, but also one of the neighbouring entries (c+1,r),(c,r+1),(c-1,r), or (c,r-1), is covered depending on the type chosen for this particular antenna. What is the least number of antennas for which there exists a placement in A such that all points of interest are covered? 

Input
On the first row of input is a single positive integer n, specifying the number of scenarios that follow. Each scenario begins with a row containing two positive integers h and w, with 1 <= h <= 40 and 0 < w <= 10. Thereafter is a matrix presented, describing the points of interest in Sweden in the form of h lines, each containing w characters from the set ['*','o']. A '*'-character symbolises a point of interest, whereas a 'o'-character represents open space. 

Output
For each scenario, output the minimum number of antennas necessary to cover all '*'-entries in the scenario's matrix, on a row of its own.
Sample Input
2
7 9
ooo**oooo
**oo*ooo*
o*oo**o**
ooooooooo
*******oo
o*o*oo*oo
*******oo
10 1
*
*
*
o
*
*
*
*
*
*
Sample Output
17
5



#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=1e3+5;

int mapp[maxn][maxn],vis[maxn][maxn],link[maxn];
bool vist[maxn];
int h,w,cnt,ip;
int dx[]={0,1,-1,0};
int dy[]={1,0,0,-1};
int dfs(int x)
{
    int i;
    for(i=1; i<=ip; i++)
    {
        if(!vist[i] && mapp[x][i])
        {
            vist[i]=true;
            if(link[i]==0 || dfs(link[i]))
            {
                link[i]=x;
                return true;
            }
        }
    }
    return false;
}
void Hungary()
{
    int i;
    cnt=0;
    for(i=1; i<=ip; i++)
    {
        memset(vist,0,sizeof(vist));
        if(dfs(i))
        {
            cnt++;
        }
    }
}

int main()
{
    int i,j,t,k,from,to;
    char s;
    cin>>t;
    while(t--)
    {
        cin>>h>>w;
        memset(mapp,0,sizeof(mapp));
        memset(link,0,sizeof(link));
        memset(vis,0,sizeof(vis));
        ip=0;
        for(i=1;i<=h;i++)
            for(j=1;j<=w;j++)
        {
            cin>>s;
            if(s=='*')
                vis[i][j]=++ip;
        }
        for(i=1;i<=h;i++)
            for(j=1;j<=w;j++)
        {
            if(vis[i][j])
                for(int k=0;k<4;k++)
                {
                    int x=i+dx[k];
                    int y=j+dy[k];
                    if(vis[x][y])
                        mapp[vis[i][j]][vis[x][y]]=1;
                }
        }
        Hungary();
        printf("%d\n",ip-cnt/2);
    }
    return 0;
}

UVA - 11396

Problem B
Claw Decomposition

Input: Standard Input

Output: Standard Output

A claw is defined as a pointed curved nail on the end of each toe in birds, some reptiles, and some mammals. However, if you are a graph theory enthusiast, you may understand the following special class of graph as shown in the following figure by the word claw.

If you are more concerned about graph theory terminology, you may want to define claw as K1,3.

Let’s leave the definition for the moment & come to the problem. You are given a simple undirected graph in which every vertex has degree 3. You are to figure out whether the graph can be decomposed into claws or not.

Just for the sake of clarity, a decomposition of a graph is a list of subgraphs such that each edge appears in exactly one subgraph in the list.

Input

There will be several cases in the input file. Each case starts with the number of vertices in the graph, V (4<=V<=300). This is followed by a list of edges. Every line in the list has two integers, a & b, the endpoints of an edge (1<=a,b<=V). The edge list ends with a line with a pair of 0. The end of input is denoted by a case with V=0. This case should not be processed.

Output

For every case in the input, print YES if the graph can be decomposed into claws & NO otherwise.

Sample Input Output for Sample Input

4

1 2

1 3

1 4

2 3

2 4

3 4

0 0

6

1 2

1 3

1 6

2 3

2 5

3 4

4 5

4 6

5 6

0 0

0

NO

NO



爪是一个点连三条边,因为题目说明了每条边只能属于一个爪,所以图中边的总数应该是3的倍数,然后从每个点的度数为3,可以得到m*2 == n*3。(m为边数,n为点数)

#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<vector>
#include<map>
#include<set>
using namespace std;


#define LL long long
#define INF 1E4 * 1E9
#define pi acos(-1)
#define endl '\n'
#define me(x) memset(x,0,sizeof(x));
const int maxn=1e3+5;
const int maxx=1e6+5;

int color[maxn];  
vector<int> G[maxn];  
int dfs(int u)
{  
    for(int i = 0;i < G[u].size();i++)
    {  
        int v = G[u][i];  
        if(color[v] == color[u]) return 0;  
        if(!color[v])
        {  
            color[v] = 3 - color[u];  
            if(!dfs(v)) return 0;  
        }  
    }  
    return 1;  
}  
  
int main(){  
    int n,m;  
    while(cin>>n)
    {  
        if(n == 0) break;  
        int a,b;  
        m = 0;  
        me(color);
        for(int i = 0;i <= n;i++) G[i].clear();  
        while(cin>>a>>b)
        {  
            if(a == 0 && b == 0) break;  
            G[a].push_back(b); G[b].push_back(a);  
            m++;  
        }  
        color[1] = 1; 
        if(m*2 == n*3 && dfs(1))  puts("YES");
        else  puts("NO");
    }  
} 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值