给出一张图,问最少删除多少条边,剩下的图无奇圈。因为二分图就是无奇圈的,所以问题转换为删去最少边,来组成二分图。
注意到点很少,因此可以枚举所以点在不同的集合下的情况。然后对于在同一部分的点,只需要删除连接他们的边即可。
囧rz。忘加特判和矩阵坐标忘了偏移找了好久的错= =
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define N 20
using namespace std;
int a[N][N];
int bit[N];
int n, m;
int bitx;
int one[N], zero[N];
int t1, t2;
int get_pow( int x )
{
int res = 1;
while(x--)
{
res *= 2;
}
return res;
}
void get_bit( int x )
{
bitx = 1;
memset(bit, 0, sizeof(bit));
while(x)
{
bit[bitx++] = x % 2;
x /= 2;
}
}
void get_0_1()
{
t1 = t2 = 0;
for ( int i = 1; i <= n; i++ )
{
if( bit[i] )
one[++t1] = i;
else
zero[++t2] = i;
}
}
int main()
{
int tot;
scanf("%d", &tot);
while(tot--)
{
scanf("%d%d", &n, &m);
memset(a, 0, sizeof(a));
int u ,v;
while(m--)
{
scanf("%d%d", &u, &v);
a[v+1][u+1]++;
a[u+1][v+1]++;
}
int sum = get_pow(n);
int minn = 999999;
if( n == 1 || m == 0 || n == 0 )
{
printf("0\n");
continue;
}
for( int i = 1; i < sum-1; i++ )
{
get_bit(i);
get_0_1();
int tmp = 0;
for( int j = 1; j <= t1; j++ )
{
for( int k = j+1; k <= t1; k++ )
{
tmp += a[one[j]][one[k]];
}
}
for( int j = 1; j <= t2; j++ )
{
for ( int k = j+1; k <= t2; k++ )
{
tmp += a[zero[j]][zero[k]];
}
}
minn = minn < tmp? minn : tmp;
}
printf("%d\n", minn);
}
return 0;
}

本文讨论了如何通过最小化删除边的数量,将给定的图转换为无奇圈的二分图。通过枚举点在不同集合下的情况,并仅删除连接同一集合内点的边,实现目标。特判和矩阵坐标偏移的错误导致了长时间的调试。

513

被折叠的 条评论
为什么被折叠?



