【二分图匹配 练习】洛谷P3386【模板】二分图最大匹配P2756飞行员配对方案问题P1129矩阵游戏P1559运动员最佳匹配问题P4014分配问题P1640连续攻击游戏

这些代码实现了一系列图论问题的解决方案,包括二分图最大匹配、飞行员配对、矩阵游戏和运动员最佳匹配。它们使用了深度优先搜索(DFS)策略,并通过调整权重来优化匹配过程。在洛谷P1129矩阵游戏中,检查是否存在完全匹配;在洛谷P1559运动员最佳匹配问题中,展示了两种不同方法的效率比较;洛谷P4014分配问题中,通过调整边的权重寻找最优分配。代码中还展示了如何避免因未初始化变量导致的错误。
摘要由CSDN通过智能技术生成

洛谷 P3386【模板】二分图最大匹配

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
typedef long long int LL;
const int N = 505;
int mp[N][N],link[N],vis[N];
int n,m,e,u,v,ans;
bool dfs(int x)
{
    for(int i=1; i<=m; i++){
        if(!vis[i] && mp[x][i]){
            vis[i] = 1;
            if(!link[i] || dfs(link[i])){
                link[i] = x;
                return true;
            }
        }
    }
    return false;
}
int main()
{
    scanf("%d%d%d",&n,&m,&e);
    for(int i=0; i<e; i++){
        scanf("%d%d",&u,&v);
        mp[u][v] = 1;
    }
    for(int i=1; i<=n; i++) {
        memset(vis,0,sizeof(vis));
        ans += dfs(i);
    }
    printf("%d",ans);
    return 0;
}

洛谷 P2756飞行员配对方案问题

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
typedef long long int LL;
const int N = 105;
int mp[N][N],vis[N],link[N];
int n,m,u,v,ans;
bool dfs(int x)
{
    for(int i=1; i<=n; i++){
        if(!vis[i] && mp[x][i]){
            vis[i] = 1;
            if(!link[i] || dfs(link[i])){
                link[i] = x;
                return true;
            }
        }
    }
    return false;
}
int main()
{
    scanf("%d%d",&m,&n);
    n-=m;
    while(scanf("%d%d",&u,&v)){
        if(u == -1 && v == -1) break;
        mp[u][v-m] = 1;
    }
    for(int i=1; i<=m; i++) {
        memset(vis,0,sizeof(vis));
        ans += dfs(i);
    }
    printf("%d\n",ans);
    for(int i=1; i<=n; i++){
        if(link[i]) printf("%d %d\n",link[i],i+m);
    }
    return 0;
}

洛谷 P1129 [ZJOI2007] 矩阵游戏

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
typedef long long int LL;
const int N = 205;
int mp[N][N],vis[N],link[N];
int t,n,ans;
bool dfs(int x)
{
    for(int i=1; i<=n; i++){
        if(!vis[i] && mp[x][i]){
            vis[i] = 1;
            if(!link[i] || dfs(link[i])){
                link[i] = x;
                return true;
            }
        }
    }
    return false;
}
int main()
{
    scanf("%d",&t);
    while(t--){
        memset(link,0,sizeof(link));
        ans = 0;
        scanf("%d",&n);
        for(int i=1; i<=n; i++){
            for(int j=1; j<=n; j++){
                scanf("%d",&mp[i][j]);
            }
        }
        for(int i=1; i<=n; i++){
            memset(vis,0,sizeof(vis));
            ans += dfs(i);
        }
        printf(ans == n ? "Yes\n" : "No\n");
    }
    return 0;
}

洛谷P1559 运动员最佳匹配问题

两种敲代码方法,一种dfs完算tmp,一种在dfs中算tmp。不确定是否一种比另一种更优,这道题后者时间占优,然而下一道题洛谷 P4014 分配问题前者时间占优。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
typedef long long int LL;
const int N = 205,INF = 0x7fffffff;
int mp[N][N],lx[N],ly[N],visx[N],visy[N],link[N];
int n,tmp,v;
bool dfs(int x)
{
    visx[x] = 1;
    for(int i=1; i<=n; i++){
        if(!visy[i] && lx[x]+ly[i]==mp[x][i]){
            visy[i] = 1;
            if(!link[i] || dfs(link[i])){
                link[i] = x;
                return true;
            }
        }
    }
    return false;
}
int one()
{
    int ans = 0;
    for(int i=1; i<=n; i++) for(int j=1; j<=n; j++){
        lx[i] = std::max(lx[i],mp[i][j]);
    }
    for(int i=1; i<=n; i++){
        while(true){
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));
            tmp = INF;
            if(dfs(i)) break;
            for(int i=1; i<=n; i++) if(visx[i]){
                for(int j=1; j<=n; j++) if(!visy[j]){
                    tmp = std::min(tmp,lx[i]+ly[j]-mp[i][j]);
                }
            }
            for(int j=1; j<=n; j++){
                if(visx[j]) lx[j] -= tmp;
                if(visy[j]) ly[j] += tmp;
            }
        }
    }
    for(int i=1; i<=n; i++){
        ans += ly[i] + lx[link[i]];
        //std::cout << "ly[" << i << "] = " << ly[i] << " lx[" << link[i] << "] = " << lx[link[i]] << " ans = " << ans << std::endl;
    }
    return ans;
}
int main()
{
    //freopen("D:\\EdgeDownloadPlace\\P4014_1.in","r",stdin);
    scanf("%d",&n);
    for(int i=1; i<=n; i++) for(int j=1; j<=n; j++){
        scanf("%d",&v);
        mp[i][j] = -v;
    }
    for(int i=0; i<N; i++) lx[i] = -INF;
    printf("%d\n",-one());
    for(int i=1; i<=n; i++) for(int j=1; j<=n; j++){
        mp[i][j] = -mp[i][j];
    }
    memset(lx,0,sizeof(lx));
    memset(ly,0,sizeof(ly));
    memset(link,0,sizeof(link));
    printf("%d\n",one());
    return 0;
}
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
typedef long long int LL;
const int N = 23,INF = 0x7fffffff;
int mp[N][N],vm[N],vf[N],vism[N],visf[N],link[N];
int n,v,ans,tmp;
bool dfs(int x)
{
    vism[x] = 1;
    for(int i=1; i<=n; i++){
        if(!visf[i]){
            int t = vm[x]+vf[i]-mp[x][i];
            if(t==0){
                visf[i] = 1;
                if(!link[i] || dfs(link[i])){
                    link[i] = x;
                    return true;
                }

            }
            else if(t>0){
                tmp = std::min(t,tmp);
            }
        }
    }
    return false;
}
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) {
        scanf("%d",&mp[i][j]);
    }
    for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) {
        scanf("%d",&v);
        mp[j][i] *= v;
    }
    for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) {
        vm[i] = std::max(vm[i],mp[i][j]);
    }
    for(int i=1; i<=n; i++){
        while(true){
            memset(visf,0,sizeof(visf));
            memset(vism,0,sizeof(vism));
            tmp = INF;
            if(dfs(i))break;
            for(int i=1; i<=n; i++){
                if(visf[i]) vf[i] += tmp;
                if(vism[i]) vm[i] -= tmp;
            }
        }
    }
    for(int i=1; i<=n; i++){
        ans += vf[i] + vm[link[i]];
    }
    printf("%d",ans);
    return 0;
}

洛谷 P4014 分配问题

全WA,我的输出莫名其妙出现了"-",洛谷判题机的锅?
破案了,one()里的ans没初始化,Windows自动给个0,Linux就挂了,初始化成0就好了

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>	
typedef long long int LL;
const int N = 105,INF = 0x7fffffff;
int mp[N][N],lx[N],ly[N],visx[N],visy[N],link[N];
int n,tmp,v;
bool dfs(int x)
{
    visx[x] = 1;
    for(int i=1; i<=n; i++){
        if(!visy[i] && lx[x]+ly[i]==mp[x][i]){
            visy[i] = 1;
            if(!link[i] || dfs(link[i])){
                link[i] = x;
                return true;
            }
        }
    }
    return false;
}
int one()
{
    int ans;
    for(int i=1; i<=n; i++) for(int j=1; j<=n; j++){
        lx[i] = std::max(lx[i],mp[i][j]);
    }
    for(int i=1; i<=n; i++){
        while(true){
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));
            tmp = INF;
            if(dfs(i)) break;
            for(int i=1; i<=n; i++){
                if(visx[i]){
                    for(int j=1; j<=n; j++){
                        if(!visy[j]){
                            tmp = std::min(tmp,lx[i]+ly[j]-mp[i][j]);
                        }
                    }
                }
            }
            for(int j=1; j<=n; j++){
                if(visx[j]) lx[j] -= tmp;
                if(visy[j]) ly[j] += tmp;
            }
        }
    }
    for(int i=1; i<=n; i++){
        ans += ly[i] + lx[link[i]];
    }
    return ans;
}
int main()
{
    //freopen("D:\\EdgeDownloadPlace\\P4014_1.in","r",stdin);
    scanf("%d",&n);
    for(int i=1; i<=n; i++) for(int j=1; j<=n; j++){
        scanf("%d",&v);
        mp[i][j] = -v;
    }
    for(int i=0; i<N; i++) lx[i] = -INF;
    printf("%d\n",-one());
    for(int i=1; i<=n; i++) for(int j=1; j<=n; j++){
        mp[i][j] = -mp[i][j];
    }
    memset(lx,0,sizeof(lx));
    memset(ly,0,sizeof(ly));
    memset(link,0,sizeof(link));
    printf("%d\n",one());
    return 0;
}

洛谷 P1640连续攻击游戏

匈牙利优化 每次memset置零vis数组太慢了,TLE,直接开一个变量timmer当作时间计数,当timmer-vis[x]>0就说明在这次dfs中x节点没有访问过。
.
初始timmer为1, 每次dfs后timmer自增1

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
typedef long long int LL;
const int INF = 0x7fffffff, SCF = 0x3fffffff;
const int N = 1e6+5, M = 220, K = 1e6+4;
int head[N],link[N],vis[N];
int n,idx,a,b,timmer;
struct Edge
{
    int to,nxt;
}edg[N<<1];
void addE(int fr,int to)
{
    edg[idx].to = to;
    edg[idx].nxt = head[fr];
    head[fr] = idx++;
}
bool dfs(int x)
{
    for(int e=head[x]; e; e=edg[e].nxt){
        int y = edg[e].to;
        if(timmer-vis[y]>0){
            vis[y] = timmer;
            if(!link[y] || dfs(link[y])){
                link[y] = x;
                return true;
            }
        }
    }
    return false;
}
int main()
{
    idx = 2;
    scanf("%d",&n);
    for(int i=1; i<=n; i++){
        scanf("%d%d",&a,&b);
        addE(a,i);
        addE(b,i);
    }
    int i;
    for(i=1; i<=n; i++){
        timmer = i;
        if(!dfs(i)) break;
    }
    printf("%d",i-1);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值