HDU 1150:
http://acm.hdu.edu.cn/showproblem.php?pid=1150
两台机器,有n和m个工作模式,起始工作模式都为0,现在有k件工作,第i件工作可分别在两个机器上用各自的模式工作,但换模式要重启,问重启的最小次数。
写的时候因为是找二分最大匹配的题目时找到写的,想到了二分上去,也知道是求最小覆盖点 == 最大匹配数,但不是很能理解,先把代码写了再说。
写的时候注意起始模式是0,所以换模式时把0的排除再外。(因为这个原因错了很多次)
一:邻接阵做法
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;
}
二:动态邻接表做法.
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
最小路径覆盖(选取最少的边覆盖所有的点) == 节点数 - 最大匹配数
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数组时算错。
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。
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: