hdu4619-网络流-最大独立集-或者是二分图

题意:
给定m,n,下面是m个棍子的横坐标,(题目中可能不是棍子是扑克,不过差不多),这种棍子只能横着放,即占用 x,y 和 x+1,y;
下面是n个竖着放置的棍子,只占用 x,y 和x,y+1;(不能往下啊)
,问可以去掉一些棍子,最大有多少棍子没有重叠。
一开始以为是水题,后来就是各种wa,我也想不到是网络流,后来写了一个dinic,也是错误百出。
错误1 没有把vector给初始化。
错误2 maxn开小了。
图论太神奇了。amazing!
此题也是 dinic模板题。属于比较简单的。
或者用二分图,上匈牙利算法;
通过最大匹配来求最大独立集。
和网络流的思路差不多,这些东西,挑战程序设计竞赛中都有讲

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
using namespace std;
const int maxn=2000;
vector<int>G[maxn];
int n,m;
void add(int u,int v)
{  G[u].push_back(v);
   G[v].push_back(u);
   //printf("\n%d******%d\n",u,v);
}
int used[maxn];
int match[maxn];
bool dfs(int v)//这次dfs的点
{
    used[v]=true;
   for(int i=0;i<G[v].size();i++)
   {   int x=G[v][i]; int w=match[x];
        if(w<0||!used[w]&&dfs(w))
         {   match[v]=x;
             match[x]=v;
             return true;
         }

   }
  return false;

}
int matching()
{  int res=0;
   memset(match,-1,sizeof(match));
 for(int v=1;v<=m;v++)
 {   if(match[v]<0)
     {  memset(used,0,sizeof(used));
        if(dfs(v))
        {  res++;

        }


     }


 }
    printf("%d\n",m+n-res);

}
int main()
{
   int a,b;
    pair<int,int>x[maxn];
   while(~scanf("%d%d",&m,&n),m+n)
   {   for(int i=0;i<maxn;i++)
      G[i].clear();
       for(int i=1;i<=m;i++)
         {   scanf("%d%d",&a,&b);
              x[i]=make_pair(a,b);
         }
         for(int i=m+1;i<=m+n;i++)
         {   scanf("%d%d",&a,&b);
             x[i]=make_pair(a,b);
         }
         //for(int i=1;i<=m+n;i++)
         //{   cout<<x[i].first<<x[i].second<<endl;

         //}

           for(int i=1;i<=m;i++)
               for(int j=m+1;j<=m+n;j++)
              {   if(x[i].first==x[j].first&&x[i].second==x[j].second)
                     {add(i,j);
                     //cout<<i<<"**"<<j<<endl;
                     }
                  if(x[i].first==x[j].first&&x[i].second==x[j].second+1)
                     {add(i,j);
                      //cout<<i<<"**"<<j<<endl;
                     }
                   if(x[i].first+1==x[j].first&&x[i].second==x[j].second)
                      {add(i,j);
                     //cout<<i<<"**"<<j<<endl;
                     }
                   if(x[i].first+1==x[j].first&&x[i].second==x[j].second+1)
                     {add(i,j);
                     //cout<<i<<"**"<<j<<endl;
                     }

           }
           /*for(int i=1;i<=m;i++)
           {   for(int j=0;j<G[i].size();j++)
                printf("****%d ",G[i][j]);
                cout<<endl;

           }*/
         matching();




   }



    return 0;
}
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
//具体思路:
/*先建边,怎么可是怎么建边呢,
*/
const int maxn=3000;
struct Node
{
    int a,b;
};
Node x[maxn];
Node y[maxn];
int level[maxn];
int iter[maxn];
struct Tree
{   int to,rev,value;
    Tree(int a,int b,int c)
    {    to=a;
         value=b;
         rev=c;
    }
};
vector<Tree>G[maxn];
int m,n;
void add(int i,int j)
{   G[i].push_back(Tree(j,1,G[j].size()));
    G[j].push_back(Tree(i,0,G[i].size()-1));
    //顺便也记录了反向边得了;
}
void bfs(int s){
    memset(level,-1,sizeof(level));
    queue<int>que;level[s]=0;
    que.push(s);
    while(!que.empty()){
        int v=que.front();que.pop();
        for(unsigned int i=0;i<G[v].size();i++){
            Tree &e=G[v][i];
            if(e.value>0&&level[e.to]<0){
                level[e.to]=level[v]+1;
                que.push(e.to);
            }
        }
    }
}
int dfs(int v,int t,int f){
    if(v==t) return f;
    for(int &i=iter[v];i<G[v].size();i++){
        Tree &e=G[v][i];
        if(e.value>0&&level[v]<level[e.to]){
            int d=dfs(e.to,t,min(f,e.value));
            if(d>0){
                e.value-=d;
                G[e.to][e.rev].value+=d;
                return d;
            }
        }
    }
    return 0;
}
int max_flow(int s,int t){
    int flow=0;
    while(1){
        bfs(s);
        if(level[t]<0)
        {printf("%d\n",m+n-flow);
        return 0;
        }
        memset(iter,0,sizeof(iter));
        int f;
        while((f=dfs(s,t,0x3f3f3f3f))>0) flow+=f;
    }
}
bool check(int d,int f)
{  //printf("%d  %d\n%d  %d\n",x[d].a,x[d].b,x[f].a,x[f].b);

    if(x[d].a==x[f].a&&x[d].b==x[f].b)
    return 1;
    if(x[d].a==x[f].a&&x[d].b==x[f].b+1)
        return 1;
    if(x[d].a+1==x[f].a&&x[d].b==x[f].b)
        return 1;
    if(x[d].a+1==x[f].a&&x[d].b==x[f].b+1)
    return 1;
    return 0;
}
int main()
{    int a,b;
    while(~scanf("%d%d",&m,&n),m+n)
    {    for(int x=0;x<maxn;x++)
             G[x].clear();

        for(int i=1;i<=m;i++)
         {   scanf("%d%d",&a,&b);
             x[i].a=a;
             x[i].b=b;
         }
         for(int i=1+m;i<=n+m;i++)
         {   scanf("%d%d",&a,&b);
             x[i].a=a;
             x[i].b=b;
         }
        for(int i=1;i<=m;i++)
        {   for(int j=m+1;j<=n+m;j++)
             {  if(check(i,j))
                 {  add(i,j);
                 //printf("***%d %d\n",i,j);
                 }
             }
        } //见图;
       for(int i=1;i<=m;i++)
           add(m+n+1,i);
       for(int j=m+1;j<=n+m;j++)
          add(j,m+n+2);
           /*for(int i=0;i<=m+n+1;i++)
    {for(int j=0;j<G[i].size();j++)
         printf("%d ",G[i][j].to);
         printf("\n");}*/
        max_flow(m+n+1,m+n+2);
    }
    return

“`
http://blog.csdn.net/dark_scope/article/details/8880547
这是是讲匈牙利的连接,挺好的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值