hdu 5313 Bipartite Graph(dfs+背包)

题意:n个点m条边,每条边的两个端点已知,求构成完全二分图能加的最多的边数;

参考:http://blog.csdn.net/acmhonor/article/details/47072399

思路:并不是一个二分图的题。。。

n个点构成完全二分图是,两边的点数差值最小时边数最多(X+Y=n,求max(x*y));

即在给定一些边的情况下,要求的是将点分在两个集合中数量差最小的情况;

先求出每个联通块中的点的情况,考虑孤立点的个数,通过贪心实现剪枝;

非贪心的情况使用背包,背包容量为n/2,推出最优解;

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int t,n,m,top,minnn;
int sum1,sum2,num,num1,num2;
int sta[2][50010];
int dp[500010];
struct node{
    int to,next;
}g[500010];
int head[500010],vis[500010];
void add(int u,int v)
{
    g[top].to=v;
    g[top].next=head[u];
    head[u]=top++;
}
void dfs(int x)
{
    if(vis[x]==-1)
        vis[x]=0;
    for(int i=head[x];i!=-1;i=g[i].next)
    {
        int v=g[i].to;
        if(vis[v]==-1)
        {
            vis[v]=1-vis[x];
            if(vis[v]==0) sum1++;
            else sum2++;
            dfs(v);
        }
    }
}
int main()
{
    int i,j,k,a,b;
    while(scanf("%d",&t)!=EOF)
    {
        while(t--)
        {
            memset(head,-1,sizeof(head));
            memset(vis,-1,sizeof(vis));
            scanf("%d%d",&n,&m);
            top=0;sum1=0;sum2=0;
            for(i=0;i<m;i++){
              scanf("%d%d",&a,&b);
              add(a,b);
              add(b,a);
            }
            top=0;num=0;num1=num2=0;
            for(i=1;i<=n;i++)
            {
                if(vis[i]==-1)
                {
                    sum1=1;sum2=0;
                    dfs(i);
                    sta[0][top]=sum1;
                    sta[1][top++]=sum2;
                    if(sum2==0){
                      num++;
                    }
                    else if(num1<num2){
                      num1+=max(sum1,sum2);
                      num2+=min(sum1,sum2);
                    }
                    else{
                      num1+=min(sum1,sum2);
                      num2+=max(sum1,sum2);
                    }
                }
            }
            if(abs(num1-num2)<=num){
               printf("%d\n",((n+1)/2)*(n/2)-m);
               continue;
            }
            int minn=-1;
            for(i=0;i<top;i++)
            {
                int ans=0;
                for(j=n/2;j>=sta[0][i]||j>=sta[1][i];j--){
                        if(j>=sta[0][i]&&ans<dp[j-sta[0][i]]+sta[0][i]&&dp[j-sta[0][i]]>=minn) //每个联通块必须选一个
                        ans=dp[j-sta[0][i]]+sta[0][i];
                        if(j>=sta[1][i]&&ans<dp[j-sta[1][i]]+sta[1][i]&&dp[j-sta[1][i]]>=minn)
                        ans=dp[j-sta[1][i]]+sta[1][i];
                        dp[j]=ans;
                        if(ans&&ans<=minnn)
                            minnn=ans;
                }
                minn=minnn;
            }
            printf("%d\n",dp[n/2]*(n-dp[n/2])-m);
        }
    }
    return 0;
}
时间: 2024-08-27 18:46:59

hdu 5313 Bipartite Graph(dfs+背包)的相关文章

HDU 5313 Bipartite Graph(二分图染色+01背包水过)

Problem Description Soda has a bipartite graph with n vertices and m undirected edges. Now he wants to make the graph become a complete bipartite graph with most edges by adding some extra edges. Soda needs you to tell him the maximum number of edges

hdu 5313 Bipartite Graph(dfs染色 或者 并查集)

Problem Description Soda has a bipartite graph with n vertices and m undirected edges. Now he wants to make the graph become a complete bipartite graph with most edges by adding some extra edges. Soda needs you to tell him the maximum number of edges

HDU 5313——Bipartite Graph——————【二分图+dp+bitset优化】

Bipartite Graph Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 840    Accepted Submission(s): 285 Problem Description Soda has a bipartite graph with n vertices and m undirected edges. Now he w

hdu 5313 Bipartite Graph 完全二分图 深搜 bitset应用

Bipartite Graph Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 577    Accepted Submission(s): 154 Problem Description Soda has a bipartite graph with n vertices and m undirected edges. Now he

HDU 5313 Bipartite Graph

题意:给一个二分图,问想让二分图变成完全二分图最多能加多少条边. 解法:图染色+dp+bitset优化.设最终的完全二分图两部分点集为A和B,A中点个数为x,B中点个数为y,边数则为x × y,答案即为x × y - m,那么用dp计算集合A中点个数的可能性.先用图染色计算每个连通分量里两种颜色点的个数,用dp[i][j]表示加入第i个连通分量时A集合中有j个点的可能性,可能为1,不可能为0,设联通分量为p,可以得到转移方程为dp[i][j] = dp[i - 1][j - p[i][0]] |

HDU 5313 Bipartite Graph (二分图着色,dp) TLE!!!

题意:Soda有一个$n$个点$m$条边的二分图, 他想要通过加边使得这张图变成一个边数最多的完全二分图. 于是他想要知道他最多能够新加多少条边. 注意重边是不允许的. 思路:二分图着色这个简单,主要是dp,还有时间限制.我觉得应该是找出所有连通分量,每个连通分量两边的点数存起来,后面统一进行DP.但是!!时间仅有1s,而且还100个例子,就是说大概要在100万的复杂度才行,可是有1万个点,当m=5000时,这就不行. 我不懂这道题如何下手才能保证一定正确且不超时,应该优化得很厉害~ 贴一个我认

2015多校第6场 HDU 5354 Bipartite Graph CDQ,并查集

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5354 题意:求删去每个点后图是否存在奇环(n,m<=1e5) 解法:很经典的套路,和这题一样:http://www.cnblogs.com/spfa/p/7358672.html CDQ套并查集. 这题最开始是看了南神的代码才懂的,http://blog.csdn.net/hdu2014/article/details/47450709    因为要判断每一个点,而且一旦一个点之外的几个点形成了奇环

[hdu 5354] Bipartite Graph 分治 并查集

题意 给定一张 $n$ 个点, $m$ 条边的无向图. 问删去每个点后, 原图是不是二分图. $1 \le n, m \le {10} ^ 5$ . 分析 一个图是二分图 $\Leftrightarrow$ 图中不存在奇环. 判定一个图是不是二分图, 可以使用并查集, 多维护一个当前点与父亲的关系的量 bond . 删除每一个点, 我们有两种维度: 区间加法, 区间减法. 这里考虑区间加法, 即考虑分治. 由于要支持撤销, 所以使用按秩合并的并查集. 注意按照大小合并... 按深度合并会 TLE

hdu 1011 Starship Troopers (依赖背包 树形dp)

题目: 链接:点击打开链接 题意: n个房间组成一棵树,你有m个战队,从1号房间开始依次clear每个房间,在每个房间需要花费的战队个数是bugs/20,得到的价值是the possibility of capturing a brain,求最大的价值. 算法: 树形dp,有依赖的背包问题.(依次clear每个房间) 思路: 状态转移dp[i][j]表示根结点为i时(房间i)花费j个战队能够得到的最大价值(捕捉到一个brain最大的可能值).递归求出每个根结点处的最大值,最后dp[1][m]就是