poj 3041( 最大匹配)

题意:给出一个矩阵和一些矩阵上的点,选择最少的行或列把给出的点覆盖。

思路:把行看成一个点集,列看成另一个点集,每个给出点构造一条这两个点集中的一条边。我们的问题就变成了选择最少的点把所有的边覆盖。很显然这就是一个最大独立点集问题,可用最大匹配求解。

匈牙利匹配算法:

View Code
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 using namespace std;
 5 #define N 10010
 6 #define M 20020
 7 struct edge{
 8     int to,next;
 9 }e[M];
10 int pre[N],visit[N],p[N];
11 int cnt;
12 void add(int a,int b)
13 {
14     e[cnt].next=pre[a];
15     e[cnt].to=b;
16     pre[a]=cnt++;
17 }
18 bool dfs(int u)
19 {
20     for(int edg=pre[u];edg!=0;edg=e[edg].next)
21     {
22         int v=e[edg].to;
23         if(visit[v])continue;
24         visit[v]=1;
25         if(!p[v]||dfs(p[v]))
26         {
27             p[v]=u;
28             return true;
29         }
30     }
31     return false;
32 }
33 int main()
34 {
35     int n,m;
36     while(scanf("%d%d",&n,&m)!=EOF)
37     {
38         cnt=1;
39         int c=0;
40         memset(p,0,sizeof(p));
41         memset(pre,0,sizeof(pre));
42         for(int i=1;i<=m;i++){
43             int a,b;
44             scanf("%d%d",&a,&b);
45             add(a,b+n);
46             add(b+n,a);
47         }
48 
49         for(int i=1;i<=n;i++)
50         {
51             memset(visit,0,sizeof(visit));
52             if(dfs(i))c++;
53         }
54         printf("%d\n",c);
55     }
56     return 0;
57 }

最大流dinic算法(邻接矩阵实现):

View Code
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 using namespace std;
 5 #define inf 0x3f3f3f3f
 6 #define N 1010
 7 int S,T,L,R;
 8 int flow[N][N],cap[N][N],level[N],q[N];
 9 bool dinic_bfs()
10 {
11     int rear=0,tail=1;
12     q[0]=S;
13     memset(level,0,sizeof(level));
14     level[S]=1;
15     while(rear<tail)
16     {
17         int u=q[rear++];
18         for(int i=L;i<=R;i++)
19         {
20             if(!level[i]&&cap[u][i]-flow[u][i]>0)
21             {
22                 level[i]=level[u]+1;
23                 q[tail++]=i;
24             }
25         }
26     }
27     return level[T]!=0;
28 }
29 int dinic_dfs(int u,int cp)
30 {
31     int tmp=cp;
32     if(u==T)return cp;
33     for(int i=L;i<=R&&tmp;i++)
34     {
35         if(level[i]==level[u]+1&&cap[u][i]-flow[u][i]>0)
36         {
37             int t=dinic_dfs(i,min(tmp,cap[u][i]-flow[u][i]));
38             flow[u][i]+=t;
39             flow[i][u]-=t;
40             tmp-=t;
41         }
42     }
43     return cp-tmp;
44 }
45 int dinic()
46 {
47     int tf=0,f;
48     while(dinic_bfs())
49     {
50         while(f=dinic_dfs(S,inf))
51         {
52             tf+=f;
53         }
54     }
55     return tf;
56 }
57 int main()
58 {
59     int n,m;
60     while(scanf("%d%d",&n,&m)!=EOF)
61     {
62         memset(flow,0,sizeof(flow));
63         memset(cap,0,sizeof(cap));
64         S=L=0;
65         T=R=2*n+1;
66         for(int i=1;i<=m;i++)
67         {
68             int a,b;
69             scanf("%d%d",&a,&b);
70             cap[a][b+n]=1;
71         }
72         for(int i=1;i<=n;i++)
73         {
74             cap[S][i]=1;
75             cap[i+n][T]=1;
76         }
77         printf("%d\n",dinic());
78     }
79     return 0;
80 }

最大流dinic算法(邻接表实现):

View Code
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 using namespace std;
 5 #define N 1010
 6 #define M 20020
 7 #define inf 0x3f3f3f3f
 8 struct edge{
 9     int to,next,cap,flow;
10 }e[M];
11 int pre[N],level[N],q[N];
12 int cnt,S,T;
13 void add(int a,int b,int c)
14 {
15     e[cnt].to=b;
16     e[cnt].next=pre[a];
17     e[cnt].cap=c;
18     e[cnt].flow=0;
19     pre[a]=cnt++;
20 }
21 bool dinic_bfs()
22 {
23     int rear=0,tail=1;
24     q[0]=S;
25     memset(level,0,sizeof(level));
26     level[S]=1;
27     while(rear<tail)
28     {
29         int u=q[rear++];
30         for(int edg=pre[u];edg!=0;edg=e[edg].next)
31         {
32             int v=e[edg].to;
33             if(!level[v]&&e[edg].cap>e[edg].flow)
34             {
35                 level[v]=level[u]+1;
36                 q[tail++]=v;
37             }
38         }
39     }
40     return level[T]!=0;
41 }
42 int dinic_dfs(int u,int cp)
43 {
44     int tmp=cp;
45     if(u==T)return cp;
46     for(int edg=pre[u];tmp&&edg!=0;edg=e[edg].next)
47     {
48         int v=e[edg].to;
49         if(level[v]==level[u]+1&&e[edg].cap>e[edg].flow)
50         {
51             int t=dinic_dfs(v,min(tmp,e[edg].cap-e[edg].flow));
52             e[edg].flow+=t;
53             e[edg^1].flow-=t;
54             tmp-=t;
55         }
56     }
57     return cp-tmp;
58 }
59 int dinic()
60 {
61     int tf=0,f;
62     while(dinic_bfs())
63     {
64         //cout<<1<<endl;
65         while(f=dinic_dfs(S,inf))
66         {
67             //cout<<f<<endl;
68             tf+=f;
69         }
70     }
71     return tf;
72 }
73 int main()
74 {
75     int n,m;
76     while(scanf("%d%d",&n,&m)!=EOF)
77     {
78         memset(pre,0,sizeof(pre));
79         int cnt=2;
80         S=0;T=2*n+1;
81         for(int i=1;i<=m;i++)
82         {
83             int a,b;
84             scanf("%d%d",&a,&b);
85             add(a,b+n,1);
86             add(b+n,a,0);
87         }
88         for(int i=1;i<=n;i++)
89         {
90             add(S,i,1);
91             add(i,S,0);
92             add(i+n,T,1);
93             add(T,i+n,0);
94         }
95         printf("%d\n",dinic());
96     }
97     return 0;
98 }
原文地址:https://www.cnblogs.com/huangriq/p/2482655.html