Posts Tagged ‘解题报告’

POJ3020【最大匹配】

原题描述:
见原题

题目大意:
给出一张图,图中元素为’*'或者’o'。其中,相连的两个’*’可以划入一个圈中。问至少需要几个圈将所有的’*'画起来。

解题思路:
若两个点都为’*'且相连,则这两个点间有边。图中每个点化ij化为新点 i*w + j(以表示出所有点)。于是,最大匹配问题就明朗了。

代码:

#include <stdio.h>
#include <string.h>
#define MAXN 410
#define _clr(x) memset(x,0xff,sizeof(int)*MAXN)

int hungary(int m,int n,int mat[][MAXN],int* match1,int* match2){
int s[MAXN],t[MAXN],p,q,ret=0,i,j,k;
for (_clr(match1),_clr(match2),i=0;i<m;ret+=(match1[i++]>=0))
for (_clr(t),s[p=q=0]=i;p<=q&&match1[i]<0;p++)
for (k=s[p],j=0;j<n&&match1[i]<0;j++)
if (mat[k][j]&&t[j]<0){
s[++q]=match2[j],t[j]=k;
if (s[q]<0)
for (p=j;p>=0;j=p)
match2[j]=k=t[j],p=match1[k],match1[k]=j;
}
return ret;
}

int main(int argc, char *argv[]){
int iTest;
scanf(“%d”,&iTest);
int map_ap[410][410];
while(iTest–){
int h,w;
scanf(“%d %d”,&h,&w);
int i,k;
int map_in[40][10];
int n = 0;
for(i = 0; i < h * w; ++i){
for(k = 0; k < h * w; ++k){
map_ap[i][k] = 0;
}
}
for(i = 0; i < h; ++i){
char sentense_in[12];
scanf(“%s”,&sentense_in);
for(k = 0; k < w; ++k){
if(‘o’ == sentense_in[k]){
map_in[i][k] = 0;
}else if(‘*’ == sentense_in[k]){
map_in[i][k] = 1;
n++;
if(i){
if(map_in[i - 1][k]){
map_ap[i * w + k][(i - 1) * w + k] = 1;
map_ap[(i - 1) * w + k][i * w + k] = 1;
}
}
if(k){
if(map_in[i][k - 1]){
map_ap[i * w + k][i * w + k - 1] = 1;
map_ap[i * w + k - 1][i * w + k] = 1;
}
}
}else{
k–;
}
}
}
int m1[410],m2[410];
printf(“%d\n”,n – hungary(h * w,h * w,map_ap,m1,m2) / 2);
}
return 0;
}

Incoming search terms for the article:

POJ2524【并查集】

POJ2524【并查集】

题目描述:

Ubiquitous Religions

Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 5586 Accepted: 2346

Description
Thereare so many different religions in the world today that it is difficultto keep track of them all. You are interested in finding out how manydifferent religions students in your university believe in.

You know that there are n students in your university (0 < n<= 50000). It is infeasible for you to ask every student theirreligious beliefs. Furthermore, many students are not comfortableexpressing their beliefs. One way to avoid these problems is to ask m(0 <= m <= n(n-1)/2) pairs of students and ask them whether theybelieve in the same religion (e.g. they may know if they both attendthe same church). From this data, you may not know what each personbelieves in, but you can get an idea of the upper bound of how manydifferent religions can be possibly represented on campus. You mayassume that each student subscribes to at most one religion.
Input
Theinput consists of a number of cases. Each case starts with a linespecifying the integers n and m. The next m lines each consists of twointegers i and j, specifying that students i and j believe in the samereligion. The students are numbered 1 to n. The end of input isspecified by a line in which n = m = 0.
Output
Foreach test case, print on a single line the case number (starting with1) followed by the maximum number of different religions that thestudents in the university believe in.
Sample Input
10 9
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
10 4
2 3
4 5
4 8
5 8
0 0
Sample Output
Case 1: 1
Case 2: 7
Hint
Huge input, scanf is recommended.
题目大意:
给出几个人两两之间的信仰相同;要求给出最多有多少个不同的信仰集合;
数据范围:
学生数0—50000;
边界数据:
几乎没有;
可能陷进:
几乎没有;
AC代码:
#include “stdio.h”
#include “iostream”
using namespace std;
int root[100001];
int heav[100001];
void makeset(int i)
{
root = i;
heav = 1;
}
int findset(int i)
{
if (root != i)
root = findset(root);
return root;
}
void unio(int i, int j)
{
if (heav > heav[j])
{
root[j] = i;
heav = heav + heav[j];
}
else if (heav < heav[j])
{
root = j;
heav[j] = heav + heav[j];
}
else
{
root[j] = i;
heav = heav + heav[j];
}
}
int main()
{
//freopen(“e:\\in.txt”, “r”, stdin);
int count, n;
int p, q;
int t, k;
int testcase = 0;
while(scanf(“%d%d”, &count, &n) != EOF)
{
if (count == 0 && n == 0) break;
testcase++;
for (int i = 1; i <= count; ++i)
makeset(i);
while(n–)
{
scanf(“%d%d”, &p,&q);
t = findset(p);
k = findset(q);
if (t != k)
{
count–;
unio(t, k);
}

}
printf(“Case %d: %d\n”,testcase, count);
}
return 0;
}