标签:
题目链接:点击打开链接
问最多能加多少边为完全二分图,左右两侧有ln,rn个点,那么完全二分图有ln*rn条边,首先应该建图后,按照黑白染色的方式,分成一个二分图,分为二分图后,重新遍历边,找到在二分图中有作用的边的条数num,因为n个点是固定的,二分图中存在作用的边也是固定,如果想要加的边尽量多,就只能让二分图的总边数尽量的多,也就是让两边的点数尽量的接近,这是就用到了,之前没有任何边连接的点,因为它们可以加入左侧或右侧,通过它们让左右两侧的点数尽量的接近,这样ln*rn-num就是最多的加边数了。
#include <cstdio> #include <cstring> #include <queue> #include <set> #include <vector> #include <cmath> #include <map> #include <stack> #include <algorithm> using namespace std ; #define LL __int64 #define INF 0x3f3f3f3f #define PI acos(-1.0) const int mod = 1e9+7 ; const double eqs = 1e-9 ; struct node{ int u , v ; int next ; }edge[210000] ; int head[11000] , cnt ; int a[11000] ; void add(int u,int v) { edge[cnt].u = u ; edge[cnt].v = v ; edge[cnt].next = head[u] ; head[u] = cnt++ ; edge[cnt].u = v ; edge[cnt].v = u ; edge[cnt].next = head[v] ; head[v] = cnt++ ; } void dfs(int u) { int i , v ; for(i = head[u] ; i !=-1 ; i = edge[i].next) { v = edge[i].v ; if( a[v] != -1 ) continue ; a[v] = 1 - a[u] ; dfs(v) ; } } int main() { int t , n , m , l_num , r_num; int u , v , i , j ; scanf("%d", &t) ; while(t--) { scanf("%d %d", &n, &m) ; memset(head,-1,sizeof(head)) ; cnt = l_num = r_num = 0 ; while( m-- ) { scanf("%d %d", &u, &v) ; add(u,v) ; } memset(a,-1,sizeof(a)) ; for(i = 1 ; i <= n ; i++) { if( a[i] == -1 && head[i] != -1 ) { a[i] = 0 ; dfs(i) ; } } int num = 0 ; for(u = 1 ; u <= n ; u++) { if( a[u] == 1 ) r_num++ ; else if( a[u] == 0 ) l_num++ ; if( a[u] ) continue ; for(j = head[u] ; j != -1 ; j = edge[j].next) { v = edge[j].v ; if( a[v] == 0 ) continue ; num++ ; } } int k1 , k2 , c = n-l_num-r_num ; k1 = max(l_num,r_num) ; k2 = min(l_num,r_num) ; if( k1 >= k1 + c ) { k1 += c ; } else { c -= k1-k2 ; k2 = k1 ; k1 += c/2 ; k2 += c-c/2 ; } printf("%d\n", k1*k2-num ) ; } return 0 ; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/winddreams/article/details/47086819