最大匹配,最小点覆盖,最大点独立,最小边覆盖,最大边独立,最小路径覆盖
最大匹配:匈牙利算法
最小点覆盖=最大匹配
最大点独立=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; }
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; }
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; }