HDU 1150:
http://acm.hdu.edu.cn/showproblem.php?pid=1150
两台机器,有n和m个工作模式,起始工作模式都为0,现在有k件工作,第i件工作可分别在两个机器上用各自的模式工作,但换模式要重启,问重启的最小次数。
写的时候因为是找二分最大匹配的题目时找到写的,想到了二分上去,也知道是求最小覆盖点 == 最大匹配数,但不是很能理解,先把代码写了再说。
写的时候注意起始模式是0,所以换模式时把0的排除再外。(因为这个原因错了很多次)
一:邻接阵做法
#include<iostream> using namespace std; int n,m,k; int map[105][105]; //记录X,Y对应点可否连接 int vis[105]; //每次找增广路时对Y中点是否访问 int dir[105]; //Y中点匹配的X中点的位置 int find(int a) { int i; for(i=0;i<m;i++) { if(map[a][i]==1 && vis[i] == 0) { vis[i] = 1; if(dir[i] == -1 || find(dir[i])) { dir[i] = a; return 1; } } } return 0; } int main() { int i,x,y; while(scanf("%d",&n)!=EOF && n!=0) { memset(map,0,sizeof(map)); memset(dir,-1,sizeof(dir)); scanf("%d%d",&m,&k); while(k--) { scanf("%d%d%d",&i,&x,&y); if(x && y) map[x][y] = 1; //应该不能再用map[y][x] = 1 } int sum = 0; for(i=0;i<n;i++) { memset(vis,0,sizeof(vis)); if(find(i)) sum++; } printf("%d/n",sum); } return 0; }
二:动态邻接表做法.
#include<iostream> using namespace std; int n,m,k; int vis[105]; //每次找增广路时对Y中点是否访问 int dir[105]; //Y中点匹配的X中点的位置 struct edge { int from; int to; edge* next; edge() { from = to = 0; next = NULL; } }; edge* List[105]; void add_edge(int f,int t) { edge* node = new edge(); node->from = f; node->to = t; node->next = List[f]; List[f] = node; } int find(edge* node) { while(1) { if(node == NULL) { break; } int i = node->to; if(vis[i] == 0) { vis[i] = 1; if(dir[i] == -1 || find(List[dir[i]])) { dir[i] = node->from; return 1; } } node = node->next; } return 0; } int main() { int i,x,y; while(scanf("%d",&n)!=EOF && n!=0) { for(i=0;i<=n;i++)//链表清空,一开始没清空,错了很多次 { List[i] = NULL; } memset(dir,-1,sizeof(dir)); scanf("%d%d",&m,&k); while(k--) { scanf("%d%d%d",&i,&x,&y); if(x && y) add_edge(x,y); } int sum = 0; for(i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if(find(List[i])) sum++; } printf("%d/n",sum); } return 0; }
三:静态邻接表做法
HDU 1151:
http://acm.hdu.edu.cn/showproblem.php?pid=1151
最小路径覆盖(选取最少的边覆盖所有的点) == 节点数 - 最大匹配数
#include <iostream> using namespace std; #define MAXN 125 int vis[MAXN]; int link[MAXN]; int n,m; struct edge { int from; int to; edge* next; edge() { from = to = 0; next = NULL; } }; edge* List[MAXN]; void add_edge(int f,int t) { edge* node = new edge(); node->from = f; node->to = t; node->next = List[f]; List[f] = node; } bool find(edge* node) { while(1) { if(node == NULL) break; int i = node->to; if(vis[i] == 0) { vis[i] = 1; if(link[i] == 0 || find(List[link[i]])) { link[i] = node->from; return 1; } } node = node->next; } return 0; } int main() { int i; int t,x,y; scanf("%d",&t); while(t--) { memset(link,0,sizeof(link)); scanf("%d%d",&n,&m); for(i=0;i<=n;i++) { List[i] = NULL; } for(i=0;i<m;i++) { scanf("%d%d",&x,&y); add_edge(x,y); } int sum = 0; for(i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if(find(List[i])) sum++; } printf("%d/n",n-sum); } return 0; }
HDU 1068:
HDU 1281:
HDU 1498:
HDU 1528:
HDU 1501:
POJ 2724:
POJ 3216:
POJ 2239:
一道如此简单的题目我竟然连续犯了好几个错误:
1:一开始对Y数组开太小,RE;
2:忘了对邻接表进行清理;
3:算Y数组时算错。
#include <iostream> using namespace std; #define num_1 305 #define num_2 100 int n; bool vis[num_2]; int dir[num_2]; struct edge { int from; int to; edge* next; edge() { from = to = 0; next = NULL; } }; edge* T[num_1]; void add_edge(int f,int t) { edge *node = new edge(); node->to = t; node->from = f; node->next = T[f]; T[f] = node; } bool find(edge* node) { while(node != NULL) { int i = node->to; if(vis[i] == 0) { vis[i] = 1; if( dir[i] == -1 || find( T[dir[i]] ) ) { dir[i] = node->from; return true; } } node = node->next; } return false; } int solve() { int res = 0; int i; memset(dir,-1,sizeof(dir)); for(i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if(find(T[i])) res++; } return res; } void Init() { int t,p,q; int i; for(i=1;i<=n;i++) { scanf("%d",&t); while(t--) { scanf("%d%d",&p,&q); add_edge(i,(p-1)*12+q); } } } void clean() { int i; for(i=0;i<=n;i++) T[i] = NULL; } int main() { while(scanf("%d",&n)!=EOF) { Init(); int num = solve(); printf("%d/n",num); clean(); //老是忘掉 } return 0; }
POJ 2584:
一道水题,就是建图的时候比较麻烦,仔细想一下已可以很顺利出来。1Y。
#include <iostream> #include <string> using namespace std; #define num_1 25 #define num_2 105 int n; string str; bool vis[num_2]; int dir[num_2]; bool map[25][6]; struct edge { int from; int to; edge* next; edge() { from = to = 0; next = NULL; } }; edge* T[num_1]; void add_edge(int f,int t) { edge *node = new edge(); node->to = t; node->from = f; node->next = T[f]; T[f] = node; } bool find(edge* node) { while(node != NULL) { int i = node->to; if(vis[i] == 0) { vis[i] = 1; if( dir[i] == -1 || find( T[dir[i]] ) ) { dir[i] = node->from; return true; } } node = node->next; } return false; } int solve() { int res = 0; int i; memset(dir,-1,sizeof(dir)); for(i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if(find(T[i])) res++; } return res; } void Init() { int i,j,k; char s,e; int start,end; memset(map,0,sizeof(map)); scanf("%d",&n); for(i=1;i<=n;i++) { cin>>s>>e; switch(s) { case 'S':start = 1;break; case 'M':start = 2;break; case 'L':start = 3;break; case 'X':start = 4;break; case 'T':start = 5;break; } switch(e) { case 'S':end = 1;break; case 'M':end = 2;break; case 'L':end = 3;break; case 'X':end = 4;break; case 'T':end = 5;break; } for(j=start;j<=end;j++) { map[i][j] = 1; } } for(i=1;i<=5;i++) { int num; scanf("%d",&num); int count = 1; for(j=1;j<=n;j++) { if(map[j][i] == 1) { for(k=1;k<=num;k++) add_edge(j,(i-1)*20+k); } } } cin>>str; } void clean() { int i; for(i=0;i<num_1;i++) T[i] = NULL; } int main() { while(1) { cin>>str; if(str == "ENDOFINPUT") break; Init(); int num = solve(); if(num == n) printf("T-shirts rock!/n"); else printf("I'd rather not wear a shirt anyway.../n"); clean(); //老是忘掉 } return 0; }
POJ 1422:
POJ 1325:
POJ 1719:
POJ 2594:
POJ 2195:
POJ 2446:
POJ 1904:
POJ 3342:
POJ 3216:
POJ 3020: