俱乐部训练题10

P1525 [NOIP2010 提高组] 关押罪犯 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>
#include<algorithm>

using namespace std;
int n,m,pre[20005],b[20005];
struct toge
{
    int x;
    int y;
    int z;
};
toge f[100005];
bool cmp(toge xx,toge yy)
{
    return xx.z>yy.z;
}
int root(int x)
{
    if(pre[x]==x) return x;
    return pre[x]=root(pre[x]);
}
int check(int x,int y)
{
    x=root(x);
    y=root(y);
    return x==y;
}

void ad(int x,int y)
{
    x=root(x);
    y=root(y);
    pre[y]=x;
}
int main()
{
   cin>>n>>m;
   for(int i=1;i<=n;i++)
   {
       pre[i]=i;
   }
   for(int i=1;i<=m;i++)
   {
       cin>>f[i].x>>f[i].y>>f[i].z;

   }
   sort(f+1,f+1+m,cmp);
   for(int i=1;i<=m+1;i++)
   {
       
       if(check(f[i].x,f[i].y))
       {
           cout<<f[i].z;
           return 0;
       }
       else
       {
           if(!b[f[i].x]) b[f[i].x]=f[i].y;
           else
           {
               ad(b[f[i].x],f[i].y);
           }
           if(!b[f[i].y]) b[f[i].y]=f[i].x;
           else
           {
               ad(b[f[i].y],f[i].x);
           }
       }
   }
}

利用并查集来做,不需要关注那个监狱,只需要关注是否存在两个犯人在同一个监狱。

P3386 【模板】二分图最大匹配 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<iostream>
#include<cstring>
using namespace std;
int n,m,e,mapa[505][505],u,v,used[505],linker[505];
bool dfs(int x)
{
   for(int i=1;i<=m;i++)
   {
       if(mapa[x][i]&&!used[i])
       {
           used[i]=1;
           if(linker[i]==0||dfs(linker[i]))
           {
               linker[i]=x;
               return true;
           }
       }
   }
   return false;
}
int hungary()
{
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        memset(used,0,sizeof(used));
        if(dfs(i)) ans++;
    }
    return ans;
}
int main()
{
    cin>>n>>m>>e;

    for(int i=1;i<=e;i++)
    {
        cin>>u>>v;
        mapa[u][v]=1;
    }
    cout<<hungary();

}

二分图最大匹配问题的匈牙利算法

P1129 [ZJOI2007] 矩阵游戏 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<iostream>
#include<cstring>
using namespace std;
int t,n,mapa[202][202];
int used[202],judge;
int linker[202];
bool dfs(int x)
{
    for(int i=1;i<=n;i++)
    {
        if(mapa[x][i]&&!used[i])
        {
            used[i]=1;
            if(!linker[i]||dfs(linker[i]))
            {
                linker[i]=x;
                return true;
            }
        }
    }
    return false;
}
int main()
{
    cin>>t;
    while(t--)
    {
          memset(linker,0,sizeof(linker));
        cin>>n;
        for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    cin>>mapa[i][j];
                }
            }
            int a=0;
           for(int i=1;i<=n;i++)
            {
               if(mapa[i][i]==0)
               {
                    a=1;
               }

            }
            if(a==0)
            {
                cout<<"Yes"<<endl;
                continue;
            }
            judge=0;
    for(int i=1;i<=n;i++)
    {
        memset(used,0,sizeof(used));
        if(!dfs(i))
        {
            cout<<"No"<<endl;
            judge=1;
            break;
        }
    }
       if(judge==0) cout<<"Yes"<<endl;

    }

}

只要保证存在n个黑格子满足任意两个格子的行和列分别不同即可,如果采用dfs(step)的方式会超时,将表格转化为二分图用匈牙利算法有更好的效率;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值