nyoj 月老的难题

http://acm.nyist.net/JudgeOnline/problem.php?pid=239


此题为二分最大匹配入门之必备习题之一!


话不多,上代码~

代码1:邻接表+匈牙利算法(邻接矩阵貌似会tle,此题数据量较大)

 
#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
struct EdgeNode 
{     
int adjvex;    
struct EdgeNode *next; 
}; 
struct VexNode 
{     
struct EdgeNode *firstedge; 
}; 
struct VexNode alist[510]; 
int visit[501],match[510]; 
int find(int x) 
{ 
<span style="white-space:pre">	</span>int k;   
<span style="white-space:pre">	</span>struct EdgeNode *p;       
<span style="white-space:pre">	</span>p=alist[x].firstedge;    
<span style="white-space:pre">	</span>while (p)  
<span style="white-space:pre">	</span>{        
<span style="white-space:pre">	</span>k=p->adjvex;        
<span style="white-space:pre">	</span>if (!visit[k])     
<span style="white-space:pre">		</span>{
	<span style="white-space:pre">	</span>visit[k]=1;  
<span style="white-space:pre">		</span>if (!match[k]||find(match[k]))          
<span style="white-space:pre">		</span>{            
<span style="white-space:pre">		</span>match[k]=x;            
<span style="white-space:pre">		</span>return 1;           
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}       
<span style="white-space:pre">	</span>p=p->next;    
<span style="white-space:pre">	</span>}    
<span style="white-space:pre">	</span>return 0; 
} 
int main() 
{ 
<span style="white-space:pre">	</span>int n,t,k,i,ans,vi,vj;    
<span style="white-space:pre">	</span>struct EdgeNode *s; 
<span style="white-space:pre">	</span>scanf("%d",&t);  
   
<span style="white-space:pre">	</span>while (t--) 
<span style="white-space:pre">	</span> 
<span style="white-space:pre">	</span>{ 
       
<span style="white-space:pre">	</span>scanf("%d%d",&n,&k); 
      
<span style="white-space:pre">	</span>memset(alist,0,sizeof(alist)); 
      
<span style="white-space:pre">	</span>memset(match,0,sizeof(match)); 
       
<span style="white-space:pre">	</span>for (i=1;i<=k;i++) 
      
<span style="white-space:pre">	</span>{           
<span style="white-space:pre">	</span>scanf("%d%d",&vi,&vj); 
            
<span style="white-space:pre">	</span>s=(struct EdgeNode*)malloc(sizeof(struct EdgeNode)); 
           
<span style="white-space:pre">	</span>s->adjvex=vj; 
          
<span style="white-space:pre">	</span>s->next=alist[vi].firstedge; 
          
<span style="white-space:pre">	</span>alist[vi].firstedge=s; 

<span style="white-space:pre">	</span>} 
    
<span style="white-space:pre">	</span>for (i=1,ans=0;i<=n;i++) 
    
<span style="white-space:pre">	</span>{ 
        
<span style="white-space:pre">	</span>memset(visit,0,sizeof(visit)); 
      
<span style="white-space:pre">	</span>if (find(i)) ans++; 
<span style="white-space:pre">	</span>       
<span style="white-space:pre">	</span>} 
        
<span style="white-space:pre">	</span>printf("%d\n",ans); 
   
<span style="white-space:pre">	</span>} 
   
<span style="white-space:pre">	</span>return 0; 
}

</pre><pre name="code" class="cpp"><img src="https://img-blog.csdn.net/20140807152147938?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQVExNEFRMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
</pre><pre name="code" class="cpp">
代码2:最大流
      思路:在原二分图的基础上,做几点修改,增加一个超级源点,并把源点和集合U(设二分图的点为两个集合U和V)中的每个点连成有向边,容量为1,再增加一个超级汇点,并把集合V中的每个点于汇点连成有向边,容量为1。
     #include<iostream>
using namespace std;
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>


#define MAXM 30010 
#define MAXN 1010
#define oo 0x7fffffff


struct Dinic  
{  
      struct node   
      {  
             int x,y,c,next;  
      }line[MAXM];     
      int Lnum,_next[MAXN],dis[MAXN];  
      void initial(int n)   
      {  
             for (int i=0;i<=n;i++) _next[i]=-1;  
             Lnum=-1;  
      }   
      void addline(int x,int y,int c)  
      {  
             line[++Lnum].next=_next[x],_next[x]=Lnum;  
             line[Lnum].x=x,line[Lnum].y=y,line[Lnum].c=c;  
             line[++Lnum].next=_next[y],_next[y]=Lnum;  
             line[Lnum].x=y,line[Lnum].y=x,line[Lnum].c=0;               
      }  
      int BFS(int s,int e)  
      {   
             queue<int> Q;  
             while (!Q.empty()) Q.pop();  
             memset(dis,-1,sizeof(dis));  
             dis[s]=0;  
             Q.push(s);  
             while (!Q.empty())  
             {  
                   int h,k;  
                   h=Q.front(),Q.pop();  
                   if (h==e) return dis[e];  
                   for (k=_next[h];k!=-1;k=line[k].next)  
                      if (line[k].c && dis[line[k].y]==-1)  
                         dis[line[k].y]=dis[h]+1,Q.push(line[k].y);                   
             }   
             return false;  
      }  
      int dfs(int x,int flow,int e)    
      {       
             if (x==e) return flow;     
             int temp,cost=0;    
             for (int k=_next[x];k!=-1;k=line[k].next)    
             if (line[k].c && dis[line[k].y]==dis[x]+1)    
             {    
                    temp=dfs(line[k].y,min(flow-cost,line[k].c),e);     
                    if (temp)    
                    {    
                           line[k].c-=temp,line[k^1].c+=temp;    
                           cost+=temp;    
                           if (flow==cost) return cost;    
                    }else dis[line[k].y]=0;    
             }    
             return cost;    
      }    
      int MaxFlow(int s,int e)  
      {  
             int MaxFlow=0;  
             while (BFS(s,e)) 
                MaxFlow+=dfs(s,oo,e);   
             return MaxFlow;  
      }  
}T;   


int main()
{
    int t;
    scanf("%d",&t); 
    while (t--)
          {
          int n,k;
          scanf("%d%d",&n,&k);
          int N=2*n+1;
          T.initial(N);
          int v1[501],v2[501];
          memset(v1,0,sizeof(v1));
          memset(v2,0,sizeof(v2)); 
          for (int i=0;i<k;++i)
              {
              int u,v;
              scanf("%d%d",&u,&v);
              T.addline(u,v+n,1);
              if (v1[u]==0)
                 {
                 v1[u]=1;
                 T.addline(0,u,1);
                 }
              if (v2[v]==0)
                 {
                 v2[v]=1;
                 T.addline(v+n,N,1);
                 }
              }
          int ans=T.MaxFlow(0,N); 
          
          printf("%d\n",ans);
          }
    return 0;
} #include<iostream>
using namespace std;
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>


#define MAXM 30010 
#define MAXN 1010
#define oo 0x7fffffff


struct Dinic  
{  
      struct node   
      {  
             int x,y,c,next;  
      }line[MAXM];     
      int Lnum,_next[MAXN],dis[MAXN];  
      void initial(int n)   
      {  
             for (int i=0;i<=n;i++) _next[i]=-1;  
             Lnum=-1;  
      }   
      void addline(int x,int y,int c)  
      {  
             line[++Lnum].next=_next[x],_next[x]=Lnum;  
             line[Lnum].x=x,line[Lnum].y=y,line[Lnum].c=c;  
             line[++Lnum].next=_next[y],_next[y]=Lnum;  
             line[Lnum].x=y,line[Lnum].y=x,line[Lnum].c=0;               
      }  
      int BFS(int s,int e)  
      {   
             queue<int> Q;  
             while (!Q.empty()) Q.pop();  
             memset(dis,-1,sizeof(dis));  
             dis[s]=0;  
             Q.push(s);  
             while (!Q.empty())  
             {  
                   int h,k;  
                   h=Q.front(),Q.pop();  
                   if (h==e) return dis[e];  
                   for (k=_next[h];k!=-1;k=line[k].next)  
                      if (line[k].c && dis[line[k].y]==-1)  
                         dis[line[k].y]=dis[h]+1,Q.push(line[k].y);                   
             }   
             return false;  
      }  
      int dfs(int x,int flow,int e)    
      {       
             if (x==e) return flow;     
             int temp,cost=0;    
             for (int k=_next[x];k!=-1;k=line[k].next)    
             if (line[k].c && dis[line[k].y]==dis[x]+1)    
             {    
                    temp=dfs(line[k].y,min(flow-cost,line[k].c),e);     
                    if (temp)    
                    {    
                           line[k].c-=temp,line[k^1].c+=temp;    
                           cost+=temp;    
                           if (flow==cost) return cost;    
                    }else dis[line[k].y]=0;    
             }    
             return cost;    
      }    
      int MaxFlow(int s,int e)  
      {  
             int MaxFlow=0;  
             while (BFS(s,e)) 
                MaxFlow+=dfs(s,oo,e);   
             return MaxFlow;  
      }  
}T;   


int main()
{
    int t;
    scanf("%d",&t); 
    while (t--)
          {
          int n,k;
          scanf("%d%d",&n,&k);
          int N=2*n+1;
          T.initial(N);
          int v1[501],v2[501];
          memset(v1,0,sizeof(v1));
          memset(v2,0,sizeof(v2)); 
          for (int i=0;i<k;++i)
              {
              int u,v;
              scanf("%d%d",&u,&v);
              T.addline(u,v+n,1);
              if (v1[u]==0)
                 {
                 v1[u]=1;
                 T.addline(0,u,1);
                 }
              if (v2[v]==0)
                 {
                 v2[v]=1;
                 T.addline(v+n,N,1);
                 }
              }
          int ans=T.MaxFlow(0,N); 
          
          printf("%d\n",ans);
          }
    return 0;
} 

    



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值