hdu 5313
题意:给你一个二分图,然后问你最多加多少边能变成完全二分图
题解:先dfs染色,求出每个子图中的黑白的个数,然后应该就是dp,每个子图取黑色或白色,最后二分图两边的点为x和y,x+y=n,然后求x×y最大
然而这题不满足dp的复杂度,百度了个bitset,看着挺好用的样子,不过手残写错了几次。
然后题目里说有重边,也不知道他到底有没有,直接减去m也对
bitset:
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;
#define MAX 10005
#define MAXN 2000005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lrt rt<<1
#define rrt rt<<1|1
#define mid int m=(r+l)>>1
#define LL long long
#define ull unsigned long long
#define mem0(x) memset(x,0,sizeof(x))
#define mem1(x) memset(x,-1,sizeof(x))
#define meminf(x) memset(x,INF,sizeof(x))
#define lowbit(x) (x&-x)
const LL mod = 1000000;
const int prime = 999983;
const int INF = 0x3f3f3f3f;
const int INFF = 1e9;
const double pi = 3.141592653589793;
const double inf = 1e18;
const double eps = 1e-10;
/**************读入外挂**********************/
inline int read_int(){
int ret=0;
char tmp;
while(!isdigit(tmp=getchar()));
do{
ret=(ret<<3)+(ret<<1)+tmp-'0';
}while(isdigit(tmp=getchar()));
return ret;
}
/*******************************************/
struct Edge{
int v,next;
}edge[200005];
struct cha{
int a,b;
bool operator < (const cha &e)const{
return a-b>e.a-e.b;
}
}p[MAX];
int head[MAX];
int col[MAX];
int num1[MAX];
int num2[MAX];
set<int> s[MAX];
int tot;
int cnt;
int n,m;
int sum1,sum2;
void add_edge(int a,int b){
edge[tot]=(Edge){b,head[a]};
head[a]=tot++;
}
void init(){
mem1(head);
mem0(col);
mem0(num1);
mem0(num2);
tot=0;
cnt=0;
for(int i=1;i<=n;i++) s[i].clear();
}
void dfs(int u){
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(!col[v]){
col[v]=-col[u];
if(col[v]==1) sum1++;
else sum2++;
dfs(v);
}
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
init();
int tmp=0;
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
add_edge(a,b);
add_edge(b,a);
if(s[a].count(b)) continue;
tmp++;
s[a].insert(b);
s[b].insert(a);
}
for(int i=1;i<=n;i++){
if(!col[i]){
sum1=1;
sum2=0;
col[i]=1;
dfs(i);
p[cnt++]=(cha){max(sum1,sum2),min(sum1,sum2)};
}
}
bitset<10001> bi;
bi.set(0);
for(int i=0;i<cnt;i++){
bi=bi<<p[i].a|bi<<p[i].b;
}
for(int i=n/2;i>0;i--){
if(bi[i]){
printf("%d\n",i*(n-i)-tmp);
break;
}
}
}
return 0;
}
然后感觉贪心貌似也可以啊,一个子图里面黑色a,白色b个,然后先按照每个子图黑白之差排序,然后二分图的两侧,少的那一侧就加子图多的那部分点
感觉应该也没问题啊虽然百度说可能有错,但是也能AC
贪心还是要敢于写,毕竟这题dp TLE的概率远大于贪心WA的概率
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;
#define MAX 10005
#define MAXN 2000005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lrt rt<<1
#define rrt rt<<1|1
#define mid int m=(r+l)>>1
#define LL long long
#define ull unsigned long long
#define mem0(x) memset(x,0,sizeof(x))
#define mem1(x) memset(x,-1,sizeof(x))
#define meminf(x) memset(x,INF,sizeof(x))
#define lowbit(x) (x&-x)
const LL mod = 1000000;
const int prime = 999983;
const int INF = 0x3f3f3f3f;
const int INFF = 1e9;
const double pi = 3.141592653589793;
const double inf = 1e18;
const double eps = 1e-10;
/**************读入外挂**********************/
inline int read_int(){
int ret=0;
char tmp;
while(!isdigit(tmp=getchar()));
do{
ret=(ret<<3)+(ret<<1)+tmp-'0';
}while(isdigit(tmp=getchar()));
return ret;
}
/*******************************************/
struct Edge{
int v,next;
}edge[200005];
struct cha{
int a,b;
bool operator < (const cha &e)const{
return a-b>e.a-e.b;
}
}p[MAX];
int head[MAX];
int col[MAX];
int num1[MAX];
int num2[MAX];
set<int> s[MAX];
int tot;
int cnt;
int n,m;
int sum1,sum2;
void add_edge(int a,int b){
edge[tot]=(Edge){b,head[a]};
head[a]=tot++;
}
void init(){
mem1(head);
mem0(col);
mem0(num1);
mem0(num2);
tot=0;
cnt=0;
for(int i=1;i<=n;i++) s[i].clear();
}
void dfs(int u){
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(!col[v]){
col[v]=-col[u];
if(col[v]==1) sum1++;
else sum2++;
dfs(v);
}
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
init();
int tmp=0;
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
add_edge(a,b);
add_edge(b,a);
if(s[a].count(b)) continue;
tmp++;
s[a].insert(b);
s[b].insert(a);
}
for(int i=1;i<=n;i++){
if(!col[i]){
sum1=1;
sum2=0;
col[i]=1;
dfs(i);
p[cnt++]=(cha){max(sum1,sum2),min(sum1,sum2)};
}
}
bitset<10001> bi;
bi.set(0);
for(int i=0;i<cnt;i++){
bi=bi<<p[i].a|bi<<p[i].b;
}
for(int i=n/2;i>0;i--){
if(bi[i]){
printf("%d\n",i*(n-i)-tmp);
break;
}
}
}
return 0;
}