您的位置:首页 > 其它

暑期训练赛(6)C

2014-08-05 18:21 260 查看
Prison rearrangement

Time Limit: 3000MS Memory Limit: 10000K
Total Submissions: 2209 Accepted: 995
Description
In order to lower the risk of riots and escape attempts, the boards of two nearby prisons of equal prisoner capacity, have decided to rearrange their prisoners among themselves. They want to exchange half of the prisoners
of one prison, for half of the prisoners of the other. However, from the archived information of the prisoners' crime history, they know that some pairs of prisoners are dangerous to keep in the same prison, and that is why they are separated today, i.e. for
every such pair of prisoners, one prisoners serves time in the first prison, and the other in the second one. The boards agree on the importance of keeping these pairs split between the prisons, which makes their rearrangement task a bit tricky. In fact, they
soon find out that sometimes it is impossible to fulfil their wish of swapping half of the prisoners. Whenever this is the case, they have to settle for exchanging as close to one half of the prisoners as possible.
Input
On the first line of the input is a single positive integer n, telling the number of test scenarios to follow. Each scenario begins with a line containing two non-negative integers m and r, 1 < m < 200 being the number
of prisoners in each of the two prisons, and r the number of dangerous pairs among the prisoners. Then follow r lines each containing a pair xi yi of integers in the range 1 to m,which means that prisoner xi of the first prison must not be placed in the same
prison as prisoner yi of the second prison.
Output
For each test scenario, output one line containing the largest integer k <= m/2 , such that it is possible to exchange k prisoners of the first prison for k prisoners of the second prison without getting two prisoners
of any dangerous pair in the same prison.
Sample Input
3
101 0
3 3
1 2
1 3
1 1
8 12
1 1
1 2
1 3
1 4
2 5
3 5
4 5
5 5
6 6
7 6
8 7
8 8

Sample Output
50
0
3

Source
Northwestern Europe 2003
//AC代码
/*
这道题,如果想明白了就是一个简单的搜索和背包知识的运用。

首先,我们先一个一个的搜索左右节点之间的联系,这种联系是通过两个监狱的犯人组合在一起有危险和建立起来的,也就是说,输入时如果i,j存在联系,那么就记录他们之间有联系(map[i][j] = true)。

那么,我们怎么来计算最大的可交换组合数呢,这其实是一个01背包的问题,我们用二维数组记录两个监狱之间在不发生危险的情况下可交换的情况,如dp[i][j] = true表示第一个监狱拿出i个犯人和第二个监狱拿出j个犯人来交换是可行的,那么我们由后往前,更新所有的可能情况(01背包,初始状态dp[0][0] = true)。

最后,我们找出小于监狱人数一半的最大可交换数,只需寻找dp[i][i]=true(i<=监狱人数的一半)的情况即可。

*/
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iomanip>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
#define LL long long
#define IT __int64
#define zero(x) fabs(x)<eps
#define mm(a,b) memset(a,b,sizeof(a))
const int INF=0x7fffffff;
const double inf=1e8;
const double eps=1e-10;
const double PI=acos(-1.0);
const int Max=205;
using namespace std;
int num_a, num_b;
int vit[2][Max];
int dp[Max][Max];
int Map[Max][Max];
int n, m;
void init()
{
mm(vit,0);
mm(dp,0);
mm(Map,0);
}
void input()
{
int i,j,t;
cin>>n>>m;
for(i = 0; i < m; i++ )
{
cin>>j>>t;
Map[j][t] = 1;
}
}
void dfs(int num, int id)
{
int i;
vit[num][id] = 1;
if( num == 0 )
{
num_a++;
for(i = 1; i <= n; i++ )
{
if( Map[id][i] && !vit[1][i] )
{
dfs(1, i);
}
}
}
else
{
num_b++;
for(i = 1; i <= n; i++ )
{
if( Map[i][id] && !vit[0][i] )
{
dfs(0, i);
}
}
}
}

void ToCont()
{
int i,j;
for(i = n/2; i >= num_a; i-- )
{
for(j = n/2; j >= num_b; j-- )
{
if( dp[i-num_a][j-num_b] ) dp[i][j] = 1;
}
}
}

void output()
{
for( int i = n/2; i >= 0; i-- )
{
if( dp[i][i] )
{
cout<<i<<endl;
break;
}
}
}

int main()
{
int T, i;
cin>>T;
while(T--)
{
init();
input();
dp[0][0] = 1;
for( i = 1; i <= n; i++ )
{
if( vit[0][i] ) continue;
num_a = 0;
num_b = 0;
dfs( 0, i );
ToCont();
}
for( i = 1; i <= n; i++ )
{
if( vit[1][i] ) continue;
num_a = 0;
num_b = 0;
dfs( 1, i );
ToCont();
}
output();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  暑期训练赛6