Ural1721 Two Sides of the Same Coin 二分匹配

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

吐槽一下。。开这题的人需要有多大的勇气去读题。。。。。。给题目的长度给跪了。

题意。一大堆废话,总之就是一共有n个人,一个人能干statement或者testdata或者两样都能干,现在每一个人都一个rank,只有rank相差正好等于2的人才能配合(一个负责statement另一个负责testdata)求出最大搭配数,并且输出方案(左边statemenet,右边testdata)

题意解释完之后,马上就想到二分匹配。但这道题的二分图性质不是工作的性质。如果根据工作性质分类,那么都会的人无法处理。拆点会造成错误。这题的建图很强大。。。因为rank要正好相差2,那么rank模4小于2的两个人一定无法搭配,只有一个rank模4小于2的和大于等于2的人才能搭配,于是二分图性质出来了。。。。模4小于2的放左边,模4大于等于2的放右边,根据题意建图。。。。然后匹配。。。


题目不贴了。。。

地址:http://acm.timus.ru/problem.aspx?space=1&num=1721


#include <iostream>
#include <cstring>
#include <cmath>
#include <climits>
#include <algorithm>
#include <cstdio>
using namespace std;

const int maxn = 1005;
const int maxm = 1000050;

struct edge
{
    int to;
    int next;
}edge[maxm];

int nx,ny;
int en;
int first[maxn];
int cx[maxn],cy[maxn];
int distx[maxn],disty[maxn];
int que[maxn],head,tail;
int ans;

void init()
{
    memset(cx,-1,sizeof(cx));
    memset(cy,-1,sizeof(cy));
    memset(first,-1,sizeof(first));
    en=0;
    ans=0;
}

void add(int a, int b)
{
    edge[en].to=b;
    edge[en].next=first[a];
    first[a]=en++;
}

bool bfs()
{
    int i,j,k;
    bool flag(0);
    int h,t;
    memset(distx,0,sizeof(distx));
    memset(disty,0,sizeof(disty));
    head=tail=0;
    for(i=1;i<=nx;i++)
        if (cx[i]==-1) que[tail++]=i;
    while(head!=tail)
    {
        for(h=head,t=tail;h!=t;h=(h+1)%maxn)
        {
            i=que[h];
            for(k=first[i];k!=-1;k=edge[k].next)
            {
                j=edge[k].to;
                if(!disty[j])
                {
                    disty[j]=distx[i] + 1;
                    if(cy[j]==-1)flag=1;
                    else
                    {
                        distx[cy[j]]=disty[j] + 1;
                        que[tail]=cy[j];
                        tail=(tail+1)%maxn;
                    }
                }
            }
        }
        head=t;
    }
    return flag;
}

bool dfs(int i)
{
    int j, k;
    for (k=first[i];k!=-1;k=edge[k].next)
    {
        j=edge[k].to;
        if(disty[j]==distx[i]+1)
        {
            disty[j]=0;
            if(cy[j]==-1||dfs(cy[j]))
            {
                cx[i]=j,cy[j]=i;
                return 1;
            }
        }
    }
    return 0;
}

void Hopcroft_Karp()
{
    int i,j;
    while(bfs())
        for(i=1;i<=nx;i++)
            if(cx[i]==-1&&dfs(i))ans++;
}

struct node
{
    char name[200];
    int type,rank;
    int no;
}data[1100];
char s[200];
int xx[1100],yy[1100];
int n;

int main()
{
    while(~scanf("%d",&n))
    {
        init();
        nx=ny=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",data[i].name);
            scanf("%s",s);
            if(strcmp(s,"anything")==0)
                data[i].type=0;
            else if(strcmp(s,"statements")==0)
                data[i].type=1;
            else
                data[i].type=-1;
            scanf("%d",&data[i].rank);
            if(data[i].rank%4<2)
                data[i].no=++nx,xx[nx]=i;
            else
                data[i].no=++ny,yy[ny]=i;
        }
        for(int i=1;i<=n;i++)
        {
            if(data[i].rank%4>=2) continue;
            for(int j=1;j<=n;j++)
            {
                if(j==i) continue;
                if(data[j].rank%4<2) continue;
                if(abs(data[i].rank-data[j].rank)==2)
                {
                    if(data[i].type+data[j].type!=-2 && data[i].type+data[j].type!=2)
                    {
                        add(data[i].no,data[j].no);
                    }
                }
            }
        }
        Hopcroft_Karp();
        printf("%d\n",ans);
        for(int i=1;i<=n;i++)
        {
            if(data[i].rank%4>=2) continue;
            int u=data[i].no;
            if(cx[u]==-1) continue;
            int v=cx[u];
            u=xx[u],v=yy[v];
            int f,l;
            f=l=100;
            if(data[u].type==0 && data[v].type==0)
                f=u,l=v;
            else if(data[u].type==1)
                f=u,l=v;
            else if(data[u].type==-1)
                f=v,l=u;
            else if(data[v].type==1)
                f=v,l=u;
            else f=u,l=v;
            printf("%s %s\n",data[f].name,data[l].name);
        }
    }
    return 0;
}


[二分匹配]URAL1721Two Sides of the Same Coin 题意:给n个人,每个人都有3个参数,分别是名字,能做的事(a:statements b:testdate a、b都可以:anything),Rank 要求:一个人只能做一个事件,要两个人Rank相差2才能共同做a、b,问最多能做多少个a、b,并输出 做a人的名字 做b人的名字 很明显是二分匹配 稳定婚姻问题。 一开始按照 能做a的人->能做b的人 建图 怎么都过... 阅读详情

相关推荐

URAL 1721 Two Sides of the Same Coin二分匹配

只看最后两段就行了。。 题意就是,有些会statement,有些人会testdata,有些人两种都会。然后每个人有一个rank值,rank值相差2的两个人可以合作,求最大匹配。 注意rank值相差2的人可以相互合作,也就是说,我们要把图分成二分图,使得能跟左边任意一个节点配对的点一定在右边。这样只需将rank % 4 = 2的人放在右边节点就行了。 #include #include #

diary_yang的专栏 1331

URAL1721——匈牙利算法——Two Sides of the Same Coin

Side one Poll flew above the City. Bright street lights flashed by below. He was winding his way around needle-sharp spires of communication towers and wicker grid radiators of thermon...

dgjm4087的博客 355

URAL 1721. Two Sides of the Same Coin 二分匹配 构图

题意:有n个人,每个人各自会 statements 或者 testdata ,或者两种都会 anything 。 后面还有一个数字rank。 然后找最大匹配,要求,必须有个人会 statements 有个人会testdata。然后rank的差要正好是2。 做法:因为rank差要2。 如 0 1 |2 3 | 4 5| 6 7,如果两个数两个数直接隔开当作一个格的话,可以发现只有奇数格和偶数格才有可能会匹配。所以可以把rank%4,如果等于0 1,放一侧,如果等于 2,3 放另一侧。然后计算最大匹配

万事屋 1162

URAL - 1721 Two Sides of the Same Coin

题意:给出n个人的信息,名字、特征、排名。在排名相差2的前提下,特征为testdata可以与特征为statements的组队,特征为anything可以任何一人组队;          求最多匹配对数,并将每队名字输出; 思路:构建一个二分图。ok #include #include #include using namespace std; #define N 1111 int

wuhulala的休息室 934

二分图最大匹配(匈牙利算法) URAL 1721 Two Sides of the Same Coin

题目传送门 1 /* 2 题意:三种人,statements,testdata,anthing。要求两个人能完成s和t两个工作,且rank相差2 3 二分图匹配:此题学习建图技巧,两个集和内部一定没有边相连,rank模4小于2和大于等于2的人才能搭配,并且相差正好2, 4 两个人会的不能一样。以上条件删选出两个集合,不能按照anthin...

weixin_34066347的博客 101

URAL 1721 Two Sides of the Same Coin(二分图匹配,输出匹配对象)

题意:给出n个人的信息,名字、特征、排名。 在排名相差2的前提下,特征为testdata可以与特征为statements的组队,特征为anything可以任何一人组队; 求最多匹配对数,并将每队名字输出; 思路:将排名%4,结果小于2的一组,大于等于2的一组,则同一组中不会匹配,以此构建二分图;二分图匹配; 匈牙利算法的思想是: ...

weixin_33763244的博客 139

本地部署图像生成项目:从环境配置到API集成的完整指南

图像生成技术作为计算机视觉的重要分支,通过深度学习模型实现从文本描述到视觉内容的转换。其核心原理是基于扩散模型或生成对抗网络,通过训练海量图像-文本对学习语义与视觉特征的映射关系。这项技术的工程价值在于能够为内容创作、产品设计和自动化流程提供高效的视觉内容生产能力。在实际应用场景中,本地部署方案特别适合处理敏感数据、需要定制化流程或追求低延迟响应的团队。本文以文生图和图生图等热词功能为切入点,详细介绍了如何在普通GPU环境下完成图像处理项目的完整部署流程,包括环境准备、API接口验证和批量任务管理等关键环节

weixin_34226706的博客 393

POJ1637 Sightseeing tour 混合图的欧拉回路+最大流

混合图的欧拉回路判断方法在黑书上面有具体提到。   这里采用的方法: 先给无向边定向,让后统计每一个点的出入度,如果有一个点的出入度只差为奇数,则该图不存在欧拉回路(有向图的欧拉回路每个点的度数都是偶数,至于出度=入度,在求最大流时我们会进行调整)。 全部判断完后,开始建图。 1:把每一条无向边建成一条容量为1的弧。 2:出入度之差不为0的点: 如果出>入 则将改点和源点相连 容量为

4320

POJ2125 Destroying The Graph 二分图+最小点权覆盖+最小割

趁热打铁,再来几题,加深理解。 一样是求最小点权覆盖,同样求一个最小割,但是要求出割去了那些边,只要用最终的剩余网络进行一次遍历就可以了,比较简单。 建图:同样是一个二分图,左边的点代表去掉出边,右边的点代表去掉入边(小心别弄混),左边去掉出边的点与源点相连,容量为wi- 。右边的点与汇点相连,容量为wi+。然后更据给出的弧进行连线,权值为INF Destroying The Graph

2329

POJ1041 John's trip 无向图的欧拉回路路径输出

此题要求我们判断欧拉回路是否存在,如果存在还要用最大字典序输出。这样我们就直接吧每一个出边表连出去的边根据从小到大排序就好。这样越小的节点号越早遍历到。最后从栈顶输出的时候自然就是最大的字典序了。 至于求欧拉回路的路径这里我用了DFS,其实还有专门的一种算法叫Fleury。 用DFS的方法是,之前的是否存在的判断仍与之前相同,当判定存在的时候,在图上选择一个正确的起点(如果是回路那个点都可以当

1854

POJ1815 Friendship 枚举+拆点+最小割

本题是一个无向图,然后让我们求出去掉最少的点,可以使s和t不连通,并要求我们输出字典序最小的一种方案。 看出了是最小割,但没想到要拆点,又学到了。 建图: 1:把除了s和t外其他所有点连一条弧(i,i+n,1)(这条弧表示i没有丢失自己的联系人,没有这条弧,说明i不能喝他的朋友联系了。因为i能联系到的人我是用i+n相连的) 2:如果i知道s的号码,则连一条弧(s,i,INF),

1739

POJ2112 Optimal Milking 网络最大流+二分

先用floyd求解任意两点之间的最短距离,再构建网络,将牛与源点相连容量为1,将机器与汇点相连容量为m。然后我们二分枚举答案,将牛与机器之间连线小于枚举值得边加入网络,大于枚举值得边去掉。然后求解最大流 Optimal Milking Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 8386

1652

POJ3422 Kaka's Matrix Travels 最大费用流+拆点

最大费用流。 建图:1,对于每一个数字拆成两个点,之间连一条弧,容量为1,费用INF;            2,每两个能连通的点i和j  连(i,j) (i+n*n,j) (i,j+n*n) (i+n*n,j+n*n) 容量INF,费用0            3源点与1连,费用0,容量k,终点与n*n连,费用0容量k。 然后求一个最大费用,   Kaka's Matrix Trav

1410

POJ1985 Cow Marathon 树的直径

求一棵树的直径。 方法: 随便选一个点当做root,开始DFS找到最远的一个点,这个点一定是树直径中的一个端点(严格树,不存在环) 然后再把刚才找到的点作为ROOT 第二遍DFS,这次找到的最远的距离,就是树的直径。   Cow Marathon Time Limit: 2000MS   Memory Limit: 30000K Total Submiss

1337

POJ3308 Paratroopers 二分图+最小点权覆盖+最大流

这题是求的最小花费是个乘积,因此用log先转化为加法,最后再将答案用exp转化。 这道题目将每一个Paratrooper当做一条边,行与列分别当做节点,行与源点相连,容量为相应处理过的花费。列与汇点相连,容量为相应处理过的花费。最后把Paratrooper落下的坐标相应的行和列处理成一条容量为INF的弧。最后求一个最小割。 Paratroopers Time Limit: 1

1320

POJ1386 Play on Words 有向图欧拉通路判断

题目中给你n个字符串,问你能不能找到一种排列方案,使前一个单词的尾部字符是下一个单词的首部字母。 这里我们要将问题转化,将一个单词看成一条边。将首尾两个字符分别看做两个节点,中间字母全部忽略 比如数据1: acm ibm  acm  是一条  a->m的边 ibm    是一条   i->m的边 判断存不存一条欧拉通路能够遍历每一条边,注上述问题的单词已经被我转化为一条有向

1225

POJ2942 Knights of the Round Table 双连通分量+二分图+奇圈判断

有n个骑士,其中有m对关系恶劣 现在开会要坐在圆桌上面,可以做很多张圆桌,但是关系恶劣的两人不能坐在相邻位置,现在问你有多少个骑士不能参加会议。将关系不恶劣的其实连边 首先这道题目为什么是双联通分量而不是边双联通,因为圆桌,是一个环,每两个点之间存在两条(或以上)点不重复的路径,因此是一个双联通分量,一个联通分量重的骑士,可能组成一个圆桌会议。 至于一个联通分量的中的骑士能不能组成一个圆桌,

1184

POJ3169 Layout 差分约束

我审题果然不仔细,一直不出sample原来是看错了 求成了最小值,题目中要我们求最大值。。。。。。 这道题是一道差分约束,这题的约束关系非常的明显 ML   S[b]-S[a] MD  S[b]-S[a]>=c   转化后  S[a]-S[b] 还有相邻的两只牛之间的距离   S[i]-s[i-1]>=0  转化后  S[i-1]-S[i] 我们要求最长的排队距离就是要解出这个关系

1161
上一篇: POJ1041 John's trip 无向图的欧拉回路路径输出
下一篇: Ural1713 Key Substrings 后缀数组
Albafica
博客等级 码龄15年 98粉丝 359原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值