http://acm.hdu.edu.cn/showproblem.php?pid=2444

大意是给定n个学生,他们之间可能互相认识,首先判断能不能将这些学生分为两组,使组内学生不认识;

现想将学生两两分组,且保证每一组的学生都认识,这样分组可达到的最大组数为多大?

判断二分图,然后求匈牙利算法求最大匹配数

 

染色法判断二分图(脑抽用vector跑的特别慢)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<vector>
 4 using namespace std;
 5 #define M 300
 6 vector<int>line[M];
 7 int judge[M],p[M],q[M],used[M];
 8 int n;
 9 int find()
10 {
11     memset(q,0,sizeof(q));
12     int start=0,end=1;
13     q[start]=1;
14     memset(judge,-1,sizeof(judge));
15     judge[1]=0;
16     while (start<end)
17     {
18         int w=q[start];
19         for (int i=0;i<line[w].size();i++)
20         {
21             int e=line[w][i];
22             if (judge[e]==-1){
23                     judge[e]=(judge[w]+1)%2;
24                     q[end++]=e;
25             }
26             else{
27                 if (judge[e]==judge[w]) return 0;
28             }
29         }
30         start++;
31     }
32     return 1;
33 }
34 int sreach(int x)
35 {
36     int i,j;
37     for (j=1;j<=n;j++){
38     for (i=0;i<line[j].size();i++)
39     {
40         if (line[j][i]==x&&!used[j])
41         {
42             used[j]=1;
43             if (!p[j]||sreach(p[j]))
44             {
45                 p[j]=x;
46                 return 1;
47             }
48         }
49     }
50     }
51     return 0;
52 }
53 int main()
54 {
55     int t,i,m,a,b;
56     while (~scanf("%d %d",&n,&m))
57     {
58         for (i=0;i<=n;i++)
59             line[i].clear();
60         while (m--)
61         {
62             scanf("%d %d",&a,&b);
63             line[a].push_back(b);
64             line[b].push_back(a);
65         }
66         memset(p,0,sizeof(p));
67         if (!find()){
68             printf("No\n");continue;
69         }
70         int ans=0;
71         for (i=1;i<=n;i++)
72         {
73             memset(used,0,sizeof(used));
74             if (sreach(i)) ans++;
75         }
76         printf("%d\n",ans/2);
77     }
78     return 0;
79 }

 

关系并查集判断二分图,类似于hdu 1829

#include<cstdio>
#include<cstring>
using namespace std;
#define M 300
int father[M],line[M][M],used[M],p[M];
int n,rank[M];
void give()
{
    for (int i=0;i<=200;i++){
        father[i]=i;rank[i]=0;
    }
}
int find(int x)
{
    if (x==father[x]) return father[x];
    int t=find(father[x]);
    rank[x]=(rank[x]+rank[father[x]])%2;
    father[x]=t;
    return father[x];
}
int sreach(int x,int n)
{
    int i;
    for (i=1;i<=n;i++)
    {
        if (line[i][x]&&!used[i])
        {
           used[i]=1;
           if (!p[i]||sreach(p[i],n))
           {
               p[i]=x;
               return 1;
           }
        }
    }
    return 0;
}
int main()
{
    int n,m,a,b,i;
    while (~scanf("%d %d",&n,&m))
    {
        give();
        int flag=0;
        memset(p,0,sizeof(p));
        memset(line,0,sizeof(line));
        while (m--)
        {
            scanf("%d %d",&a,&b);
            line[a][b]=line[b][a]=1;
            int sx=find(a);
            int sy=find(b);
            if (sx!=sy) {
                rank[sx]=(rank[a]+rank[b]+1)%2;
                father[sx]=sy;
            }
            else {
                if (rank[a]==rank[b]) flag=1;
            }
        }
        if (flag==1){
            printf("No\n");continue;
        }
        int ans=0;
        for (i=1;i<=n;i++)
        {
            memset(used,0,sizeof(used));
            if (sreach(i,n)) ans++;
        }
        printf("%d\n",ans/2);
    }
    return 0;
}

 

posted on 2015-11-10 14:30  蜘蛛侦探  阅读(182)  评论(0编辑  收藏  举报