[BZOJ 1143][CTSC 2008]祭祀river(二分图最大独立集)

来源:互联网 发布:淘宝照片处理软件 编辑:程序博客网 时间:2024/06/02 11:55

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1143

这是我做的第一道CTSC的题,这题水得我都惊呆了。。。据说BZOJ只有第一问,没有问第二问,因为没数据,难怪这么水。。。

首先我们得知道二分图的独立集的概念:

二分图的独立集是二分图中一个任意两点都不相连的顶点的集合

二分图的最大独立集求法:

二分图的最大独立集=二分图点数-二分图最大匹配

然后这题就好做了。首先我们用Floyd求出相互可达的点的点对,然后用这些点对建立一个二分图,这个二分图中,有边相连的两个点都是相互可达的。然后我们求二分图的最大独立集即可。得到的二分图最大独立集中,任意两点之间均不可达。

注意边的个数要开n^2个!因为极限情况是任意两点之间均可达

#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <algorithm>#define MAXV 110#define MAXE 100100using namespace std;struct edge{    int u,v,next;}edges[MAXE];int head[MAXV],nCount=0;int dist[MAXV][MAXV],n,m;int linky[MAXV];bool visit[MAXV];void AddEdge(int U,int V){    edges[++nCount].u=U;    edges[nCount].v=V;    edges[nCount].next=head[U];    head[U]=nCount;}bool dfs(int u){    for(int p=head[u];p!=-1;p=edges[p].next)    {        int v=edges[p].v;        if(visit[v]) continue;        visit[v]=true;        if(linky[v]==-1||dfs(linky[v]))        {            linky[v]=u;            return true;        }    }    return false;}int main(){    memset(head,-1,sizeof(head));    memset(linky,-1,sizeof(linky));    scanf("%d%d",&n,&m);    int ans=n;    for(int i=1;i<=m;i++)    {        int x,y;        scanf("%d%d",&x,&y);        dist[x][y]=1;    }    for(int k=1;k<=n;k++) //Floyd预处理,求出u能到达v的点对(u,v);        for(int i=1;i<=n;i++)            for(int j=1;j<=n;j++)                dist[i][j]|=dist[i][k]&dist[k][j];    for(int i=1;i<=n;i++)        for(int j=1;j<=n;j++)            if(i!=j)                if(dist[i][j])                    AddEdge(i,j);    for(int i=1;i<=n;i++)    {        memset(visit,false,sizeof(visit));        if(dfs(i)) ans--;    }    printf("%d\n",ans);    return 0;}



0 0
原创粉丝点击