LightOJ

来源:互联网 发布:innerhtml js不执行 编辑:程序博客网 时间:2024/06/03 09:07

匈牙利算法

#include<cstdio>#include<cstring>#include<cmath>#include<vector>using namespace std;/*求二分图的最大独立集邻接表存图匈牙利算法得到最大匹配(或最小顶点覆盖)hungary()V-hungary()=最大独立集*/const int maxn=4e4+5;//点的最大值const int maxm=5e5+5;int n;int a[maxn],b[maxm];int factor[maxn];// 质因数vector<int>G[maxn];//二分图int linker[maxn];bool used[maxn];bool dfs(int u){    for(int i=0;i<G[u].size();i++)    {        int v=G[u][i];        if(!used[v])        {            used[v]=true;            if(linker[v]==-1||dfs(linker[v]))            {                linker[v]=u;                return true;            }        }    }    return false;}//最大匹配int hungary(){    int res=0;    for(int u=1;u<=n;u++)    {        memset(used,0,sizeof(used));        if(dfs(u)) res++;    }    return res;}void init(){    memset(linker,-1,sizeof(linker));    memset(b,0,sizeof(b));    for(int i=1;i<=n;i++)    {        G[i].clear();    }}int main(){    int T,t;    scanf("%d",&T);    for(int kase=1;kase<=T;kase++)    {        init();        scanf("%d",&n);        for(int i=1;i<=n;i++)        {            scanf("%d",&a[i]);        }        for(int i=1;i<=n;i++)        {            b[a[i]]=i;//对结点hash        }        for(int i=1;i<=n;i++)        {            t=a[i];            int cnt=0,sum=0;//分解质因子            //cnt为质因数个数,sum为质因数总数            for(int j=2;t>1&&j<=sqrt(t);j++)            {                if(t%j==0)                {                    factor[cnt++]=j;                    while(t%j==0)                    {                        t=t/j;                        sum++;                    }                }            }            if(t>1)//如果t为质数            {                factor[cnt++]=t;                sum++;            }            for(int j=0;j<cnt;j++)            {                t=b[ a[i]/factor[j] ];                if(t==0)//不存在对应关系                {                    continue;                }                if(sum&1)////共有奇数个质因子                {                    G[i].push_back(t);                }                else////共有偶数个质因子                {                   G[t].push_back(i);                }            }        }        printf("Case %d: %d\n",kase,n-hungary());    }    return 0;}

Hopcroft-Karp算法

#include<cstdio>#include<cstring>#include<cmath>#include<queue>using namespace std;/*求二分图的最大独立集邻接表存图Hopcroft-Karp算法得到最大匹配(或最小顶点覆盖)MaxMatch()V-MaxMatch()=最大独立集*/#define INF 0x3f3f3f3fconst int maxn=4e4+5;//点的最大值const int maxm=5e5+5;int n;int a[maxn],b[maxm];int factor[maxn];//质因数vector<int>G[maxn];//二分图int Mx[maxn],My[maxn];int dx[maxn],dy[maxn];int dis;bool used[maxn];bool SearchP(){    queue<int>Q;    dis=INF;    memset(dx,-1,sizeof(dx));    memset(dy,-1,sizeof(dy));    for(int i=1;i<=n;i++)    {        if(Mx[i]==-1)        {            Q.push(i);            dx[i]=0;        }    }    while(!Q.empty())    {        int u=Q.front();        Q.pop();        if(dx[u]>dis) break;        int sz=G[u].size();        for(int i=0;i<sz;i++)        {            int v=G[u][i];            if(dy[v]==-1)            {                dy[v]=dx[u]+1;                if(My[v]==-1)                {                    dis=dy[v];                }                else                {                    dx[My[v]]=dy[v]+1;                    Q.push(My[v]);                }            }        }    }    return dis!=INF;}bool DFS(int u){    int sz=G[u].size();    for(int i=0;i<sz;i++)    {        int v=G[u][i];        if(!used[v]&&dy[v]==dx[u]+1)        {            used[v]=1;            if(My[v]!=-1&&dy[v]==dis) continue;            if(My[v]==-1||DFS(My[v]))            {                My[v]=u;                Mx[u]=v;                return 1;            }        }    }    return 0;}//最大匹配int MaxMatch(){    int res=0;    memset(Mx,-1,sizeof(Mx));    memset(My,-1,sizeof(My));    while(SearchP())    {        memset(used,0,sizeof(used));        //点的编号[1,n]        for(int i=1;i<=n;i++)        {            if(Mx[i]==-1&&DFS(i))            {                res++;            }        }    }    return res;}void init(){    memset(b,0,sizeof(b));    for(int i=1;i<=n;i++)    {        G[i].clear();    }}int main(){    int T,t;    scanf("%d",&T);    for(int kase=1;kase<=T;kase++)    {        init();//清空        scanf("%d",&n);        for(int i=1;i<=n;i++)        {            scanf("%d",&a[i]);        }        for(int i=1;i<=n;i++)        {            b[a[i]]=i;//对结点hash        }        for(int i=1;i<=n;i++)        {            t=a[i];            int cnt=0,sum=0;//分解质因子            //cnt为质因数个数,sum为质因数总数            for(int j=2;t>1&&j<=sqrt(t);j++)            {                if(t%j==0)                {                    factor[cnt++]=j;                    while(t%j==0)                    {                        t=t/j;                        sum++;                    }                }            }            if(t>1)//如果t为质数            {                factor[cnt++]=t;                sum++;            }            for(int j=0;j<cnt;j++)            {                t=b[ a[i]/factor[j] ];                //printf("t=%d a=%d  factor=%d\n",t,a[i],factor[j]);                if(t==0)//不存在对应关系                {                    continue;                }                if(sum&1)//共有奇数个质因子                {                    G[i].push_back(t);                    //printf("1  i=%d t=%d\n",i,t);                }                else//共有偶数个质因子                {                    G[t].push_back(i);                    //printf("2  t=%d i=%d\n",t,i);                }            }        }        printf("Case %d: %d\n",kase,n-MaxMatch());    }    return 0;}
原创粉丝点击