最大匹配,最小点覆盖,最大点独立,最小边覆盖,最大边独立,最小路径覆盖
最大匹配:匈牙利算法
最小点覆盖=最大匹配
最大点独立=n(顶点数)-最小点覆盖
最大边独立=n-最小边覆盖
最小路径覆盖=p(n/2)-最大匹配 (p*p的有向图)
1001:
hdu1150:http://acm.hdu.edu.cn/showproblem.php?pid=1150
最大匹配等于最小点覆盖:匈牙利算法模版
代码:
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int nMax = 105;
int n, m, k;
int map[nMax][nMax];
int link[nMax];
int useif[nMax];
bool can(int t)
{
for(int i = 1; i <= m; ++ i)
{
if(!useif[i] && map[t][i])
{
useif[i] = 1;
if(link[i] == -1 || can(link[i]))
{
link[i] = t;
return 1;
}
}
}
return 0;
}
int main()
{
while(1)
{
memset(map, 0, sizeof(map));
memset(link, -1, sizeof(link));
int num = 0;
scanf("%d", &n);
if(!n) break;
scanf("%d%d", &m, &k);
for(int i = 0; i < k; ++ i)
{
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
map[b][c] = 1;
}
for(int i = 1; i <= n; ++ i)
{
memset(useif, 0, sizeof(useif));
if(can(i)) ++ num;
}
printf("%d\n", num);
}
return 0;
}
1002:
hdu1498:http://acm.hdu.edu.cn/showproblem.php?pid=1498
不太好想,行和列为两个点集合,边为一个气球的坐标,判断某个颜色的气球的最大点覆盖,恰好使用每次都使用一行和一列。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 111
using namespace std;
int n,k;
int vis[maxn],link[maxn],map[maxn][maxn];
int min(int x,int y)
{
return x>y?y:x;
}
int getnum(int x,int c)
{
for(int i=1;i<=n;i++)
{
if(!vis[i]&&map[x][i]==c)
{
vis[i]=1;
if(!link[i]||getnum(link[i],c))
{
link[i]=x;
return 1;
}
}
}
return 0;
}
int dfs(int c)
{
int count=0;
memset(link,0,sizeof(link));
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
if(getnum(i,c))
count++;
}
return count;
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
if(n==0&&k==0) break;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&map[i][j]);
}
int t=0;
for(int i=1;i<=50;i++)
{
if(dfs(i)>k&&t==0)
{
printf("%d",i);
t=1;
}
else if(dfs(i)>k&&t==1)
{
printf(" %d",i);
}
}
if(t==0)
{
printf("-1\n");
}
else
printf("\n");
}
return 0;
}
1003:
hdu1068:http://acm.hdu.edu.cn/showproblem.php?pid=1068
最大点独立集=n-最小点覆盖
点用了两次,要除以2;也可以认为为双向边。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#define INF 0x7fffffff
#define maxn 1000
#define maxl 0x7fffffff
#define fi for(int i=0;i<n;i++)
#define fj for(int j=0;j<n;j++)
#define wh while(t--)
using namespace std;
int map[maxn][maxn];
int vis[maxn],link[maxn];
int n,m;
void init()
{
memset(link,-1,sizeof(link));
memset(map,0,sizeof(map));
}
bool getnum(int x)
{
for(int i=0; i<n; i++)
{
if(!vis[i]&&map[x][i])
{
vis[i]=1;
if(link[i]==-1||getnum(link[i]))
{
link[i]=x;
return 1;
}
}
}
return 0;
}
int main()
{
int b,t;
while(scanf("%d",&n)!=EOF)
{
init();
for(int i=0; i<n; i++)
{
scanf("%d: (%d)",&t,&m);
for(int j=0; j<m; j++)
{
scanf("%d",&b);
map[i][b]=1;
map[b][i]=1;
}
}
int count=0;
for(int i=0; i<n; i++)
{
memset(vis,0,sizeof(vis));
if(getnum(i))
count++;
}
printf("%d\n",n-count/2);
}
return 0;
}
1004:
hdu3289:http://acm.hdu.edu.cn/showproblem.php?pid=3829
以每个小孩为点,冲突的小孩的点相连,求最大点独立集。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#define maxn 555
using namespace std;
int n,m,p,aln,count;
int vis[maxn],link[maxn],map[maxn][maxn];
struct P
{
string like,dislike;
}pl[555];
string s1;
string s2;
int getnum(int x)
{
for(int i=1;i<=aln;i++)
{
if(!vis[i]&&map[x][i])
{
vis[i]=1;
if(!link[i]||getnum(link[i]))
{
link[i]=x;
//count+=map[x][i];
return 1;
}
}
}
return 0;
}
int main()
{
int a,b;
while(scanf("%d%d%d",&n,&m,&p)!=EOF)
{
//aln=m+n;
aln=p;
for(int i=1;i<=p;i++)
{
cin>>s1>>s2;
pl[i].like=s1;
pl[i].dislike=s2;
}
/*
for(int i=1;i<=p;i++)
{
cout<<pl[i].like<<" "<<pl[i].dislike<<endl;
}
*/
memset(map,0,sizeof(map));
for(int i=1;i<=p;i++)
{
for(int j=1;j<=p;j++)
{
if(pl[i].dislike==pl[j].like||pl[i].like==pl[j].dislike)
{
map[i][j]=1;
}
}
}
count=0;
memset(link,0,sizeof(link));
for(int i=1;i<=aln;i++)
{
memset(vis,0,sizeof(vis));
if(getnum(i))
count++;
}
printf("%d\n",aln-count/2);
}
return 0;
}
1005:
hdu1569
看了别人的代码,感觉网络流不会就没写了。
http://blog.csdn.net/l04205613/article/details/6830224
hdu1350:http://acm.hdu.edu.cn/showproblem.php?pid=1350
最大路径覆盖=n/2-二分匹配
每个车为一个点,求最大路径覆盖。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define maxn 555
using namespace std;
struct P
{
int s,e;
int x1,y1,x2,y2;
}pl[maxn];
int map[maxn][maxn];
int vis[maxn],link[maxn];
int m;
int len(int x1,int y1,int x2,int y2)
{
x1=x1>x2?x1-x2:x2-x1;
y1=y1>y2?y1-y2:y2-y1;
return x1+y1;
}
bool getnum(int x)
{
for(int i=1;i<=m;i++)
{
if(!vis[i]&&map[x][i])
{
vis[i]=1;
if(!link[i]||getnum(link[i]))
{
link[i]=x;
return 1;
}
}
}
return 0;
}
int main()
{
int t,mi,d;
scanf("%d",&t);
while(t--)
{
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d:%d",&d,&mi);
scanf("%d%d%d%d",&pl[i].x1,&pl[i].y1,&pl[i].x2,&pl[i].y2);
pl[i].s=d*60+mi;
pl[i].e=pl[i].s+len(pl[i].x1,pl[i].y1,pl[i].x2,pl[i].y2);
}
memset(map,0,sizeof(map));
for(int i=1;i<=m;i++)
{
for(int j=i+1;j<=m;j++)
{
if(pl[i].e+len(pl[i].x2,pl[i].y2,pl[j].x1,pl[j].y1)<pl[j].s)
map[i][j]=1;
}
}
int count=0;
memset(link,0,sizeof(link));
for(int i=1;i<=m;i++)
{
memset(vis,0,sizeof(vis));
if(getnum(i))
count++;
}
printf("%d\n",m-count);
}
}
1007:
hdu1151:最大路径匹配
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#define INF 0x7fffffff
#define maxn 125
#define maxl 0x7fffffff
#define fi for(int i=0;i<n;i++)
#define fj for(int j=0;j<n;j++)
#define wh while(t--)
using namespace std;
int map[maxn][maxn];
int vis[maxn],link[maxn];
int n,m;
void init()
{
memset(link,-1,sizeof(link));
memset(map,0,sizeof(map));
}
bool getnum(int x)
{
for(int i=1;i<=n;i++)
{
if(!vis[i]&&map[x][i])
{
vis[i]=1;
if(link[i]==-1||getnum(link[i]))
{
link[i]=x;
return 1;
}
}
}
return 0;
}
int main()
{
int a,b,t;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d",&n);
scanf("%d",&m);
for(int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
map[a][b]=1;
}
int count=0;
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
if(getnum(i))
count++;
}
printf("%d\n",n-count);
}
return 0;
}