hust 1024 dance party

题目描述

You are organizing a dance party. The party will be attended by n boys and n
girls. There will be several rounds of dancing. In each round, you divide the
guests into n dancing pairs. Each guest must be in exactly one pair, and each
pair must contain one boy and one girl. Each boy must dance with a different
girl in every round. Some boys and girls like each other and some do not. During
the party, each boy agrees to dance with at most k girls he doesn‘t like.
Similarly, each girl agrees to dance with at most k boys she doesn‘t like. You
are given the each pairs of boys and girls who agree to dance with each other
.Find out the maximum number of rounds you can organize.

输入

The first line contains a integer t,which means there are t cases followed.
For each case,the first line contain three integer n,m,k ,which means there are
n boys and n girls attending the party and m pairs of boys and girls who agree
to dance with each other,and each boy or girl agrees to dance with at most k
girls or boys he or she doesn‘t like.At last ,there are m lines with two
integers a,b which means boy a and girl b agree to dance with each other.
(0<n<=100,0<m<=n*n,0<k<100,0<a,b<=n)

输出

The output cotains only one integer which means the maximum number of rounds
you can organize.

样例输入

2
2 4 0
1 1
2 2
2 1
1 2
3 7 0
1 1
1 2
1 3
2 1
2 2
3 1
3 3

样例输出

2
2
这个题好久就看到了,但是由于一直不知道怎么做,故没有做,不过,最近在刷网络流的题目,于是就拿这个题来看看,原来真的是网络流的题目啊,拆边,每个男孩和女孩都拆成三条边,对于每个boy,拆成boy,boy1,boy2,然后boy到boy1连一条边,容量为inf,boy到boy2连一条边,容量为k,女孩也是;然后就是,如果boy和girl可以跳就boy1和girl1连一条边,容量为1,若不跳,则boy2,girl2连一条边,容量为1,然后在枚举答案,从最大的开始枚举,找到就是,不用再继续找,假设当前枚举到ans,则源点向每个boy连一条容量为ans的边,每个girl向汇点连一条容量为ans的边,这样就算一下最大流,当最大流为满流的时候,就满足条件,就得到答案,用Dinic算法,在最坏的情况下时间复杂度为O(n^4*n),不过数据没有那么吓人,在2s内就能出解,具体看程序


#include<map>
#include<set>
#include<stack>
#include<queue>
#include<cmath>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define inf 0x0f0f0f0f

using namespace std;

const double pi=acos(-1.0);
const double eps=1e-8;
typedef pair<int,int>pii;

const int maxn=10000+10;

struct Edge
{
int from,to,cap,flow;
};

int n,m,s,t;
vector<Edge>edges;
vector<int>G[maxn];
int d[maxn],cur[maxn];
bool vis[maxn];

void AddEdge(int from,int to,int cap)
{
Edge temp;
temp.cap=cap; temp.flow=0; temp.from=from; temp.to=to;
edges.push_back(temp);
temp.cap=0; temp.flow=0; temp.from=to; temp.to=from;
edges.push_back(temp);
m=edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}

bool BFS()
{
memset(vis,0,sizeof(vis));
queue<int>Q;
Q.push(s);
d[s]=0;
vis[s]=1;
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 (!vis[e.to] && e.cap>e.flow)
{
vis[e.to]=1;
d[e.to]=d[x]+1;
Q.push(e.to);
}
}
}
return vis[t];
}

int DFS(int x,int a)
{
if (x==t || a==0) return a;
int flow=0,f;
for (int i=cur[x];i<G[x].size();i++)
{
Edge& e=edges[G[x][i]];
if (d[x]+1==d[e.to] && (f=DFS(e.to,min(a,e.cap-e.flow)))>0)
{
e.flow+=f;
edges[G[x][i]^1].flow-=f;
flow+=f;
a-=f;
if (a==0) break;
}
}
return flow;
}

int Dinic()
{
int flow=0;
while (BFS())
{
memset(cur,0,sizeof(cur));
flow+=DFS(s,inf);
}
return flow;
}

void init()
{
for (int i=0;i<=maxn;i++) G[i].clear();
edges.clear();
}
int parr[101][101];
int find(int N,int k)
{
int ans=N;
while(1)
{
init();
for (int i=1;i<=N;i++)
{
int boy=(i-1)*3+1;
AddEdge(boy,boy+1,inf);
AddEdge(boy,boy+2,k);
int girl=(i-1)*3+1+3*N;
AddEdge(girl+1,girl,inf);
AddEdge(girl+2,girl,k);
}
for (int i=1;i<=N;i++)
for (int j=1;j<=N;j++)
{
if (parr[i][j]==0)
{
int boy=(i-1)*3+1;
int girl=(j-1)*3+1+3*N;
AddEdge(boy+2,girl+2,1);
}
else
{
int boy=(i-1)*3+1;
int girl=(j-1)*3+1+3*N;
AddEdge(boy+1,girl+1,1);
}
}
for (int i=1;i<=N;i++)
{
int boy=(i-1)*3+1;
int girl=boy+3*N;
AddEdge(s,boy,ans);
AddEdge(girl,t,ans);
}
if (Dinic()==N*ans) break;
else ans--;
}
return ans;
}

int main()
{
//freopen("in.txt","r",stdin);
int T,N,M,k;
scanf("%d",&T);
while (T--)
{
init();
scanf("%d%d%d",&N,&M,&k);
s=0;t=6*N+1;

memset(parr,0,sizeof(parr));
for (int i=1;i<=M;i++)
{
int x,y;
scanf("%d%d",&x,&y);
parr[x][y]=1;
}

printf("%d\n",find(N,k));
}
//fclose(stdin);
return 0;
}

hust 1024 dance party,布布扣,bubuko.com

时间: 2024-10-03 22:37:25

hust 1024 dance party的相关文章

HUST 1017 - Exact cover (Dancing Links 模板题)

1017 - Exact cover 时间限制:15秒 内存限制:128兆 自定评测 5584 次提交 2975 次通过 题目描述 There is an N*M matrix with only 0s and 1s, (1 <= N,M <= 1000). An exact cover is a selection of rows such that every column has a 1 in exactly one of the selected rows. Try to find o

UVALive 2659+HUST 1017+ZOJ 3209 (DLX

UVALive 2659 题目:16*16的数独.试了一发大白模板. /* * @author: Cwind */ //#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include

Dancing Link --- 模板题 HUST 1017 - Exact cover

1017 - Exact cover Problem's Link:   http://acm.hust.edu.cn/problem/show/1017 Mean: 略 analyse: A Time complexity: O(n) Source code:  #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vecto

(简单) HUST 1017 Exact cover , DLX+精确覆盖。

Description There is an N*M matrix with only 0s and 1s, (1 <= N,M <= 1000). An exact cover is a selection of rows such that every column has a 1 in exactly one of the selected rows. Try to find out the selected rows. DLX精确覆盖的模板题...... 代码如下: //HUST 1

HUST 1588 辗转数对

1588 - 辗转数对 时间限制:1秒 内存限制:128兆 155 次提交 27 次通过 题目描述 假设当前有一个数对(a, b),我们可以通过一步将这个数对变为一个新数对(a + b, b)或者是(a, a + b).初始的数对为(1, 1),你的任务是找到一个数字k,即通过最少的步数使得这个数对中至少一个数字等于n. 输入 输入包括多组数据,每组数据包括一行,每行有一个整数n. 输出 每组数据输出一行,每行一个整数n. 样例输入 5 3 样例输出 3 2 提示 第一个样例的方法是 (1,1)

HUST 1698 - 电影院 组合数学 + 分类思想

http://acm.hust.edu.cn/problem/show/1698 题目就是要把一个数n分成4段,其中中间两段一定要是奇数. 问有多少种情况. 分类, 奇数 + 奇数 + 奇数 + 奇数 奇数 + 奇数 + 奇数 + 偶数 偶数 + 奇数 + 奇数 + 奇数 偶数 + 奇数 + 奇数 + 偶数 然后奇数表达成 2 * a - 1这个样子,就能列出方程. 然后就是类似于解a1 + a2 + a3 + a4 = x的问题了. #include <cstdio> #include &l

Linux 打开文件数1024限制的原理以及解决办法

/proc/sys/fs/file-max  该文件指定了可以分配的文件句柄的最大数目. 查看最大值: [[email protected] home]# cat /proc/sys/fs/file-max  100977 [[email protected] home]# 这表明这台Linux系统最多允许同时打开(即包含所有用户打开文件数总和)100977个文件,是Linux系统级硬限制,所有用户级的打开文件数限制都不应超过这个数值.通常这个系统级硬限制是Linux系统在启动时根据系统硬件资源

【TK】1024: 手机话费

1024: 手机话费 时间限制: 1 Sec  内存限制: 32 MB提交: 2500  解决: 1250[提交][状态][下载(1元)] 题目描述 小明的手机每天消费1元,每消费K元就可以获赠1元,一开始小明有M元,问最多可以用多少天? 输入 输入包括多个测试实例.每个测试实例包括2个整数M,K(2<=k<=M<=1000).M=0,K=0代表输入结束. 输出 对于每个测试实例输出一个整数,表示M元可以用的天数. 样例输入 2 2 4 3 0 0 样例输出 3 5 1 #include

com.mysql.jdbc.PacketTooBigException: Packet for query is too large (1169 &gt; 1024)

### Cause: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (1169 > 1024). You can change this value on the server by setting the max_allowed_packet' variable. ; SQL []; Packet for query is too large (1169 > 1024). You can change