您的位置:首页 > 其它

HDU 1150 浅谈二分图最小点覆盖水题

2017-10-13 11:13 465 查看


世界真的很大

这道题基本上还是比较简单,怎么感觉最近老是在做水题。。

不要在意,即使是水题也有可以总结的地方

抱着这样的感觉来写博客。。

但是感觉字数什么的会很少吧。。

看题先:

description:

有两台机器A和B以及N个需要运行的任务。每台机器有M种不同的模式,而每个任务都恰好在一台机器上运行。如果它在机器A上运行,则机器A需要设置为模式ai,如果它在机器B上运行,则机器B需要设置为模式bi。每台机器上的任务可以按照任意顺序执行,但是每台机器每转换一次模式需要重启一次。请合理为每个任务安排一台机器并合理安排顺序,使得机器重启次数尽量少。

input:

The input file for this program consists of several configurations. The first line of one configuration contains three positive integers: n, m (n, m < 100) and k (k < 1000). The following k lines give the constrains of the k jobs, each line is a triple: i, x, y.

The input will be terminated by a line containing a single zero.

output:

The output should be one integer per line, which means the minimal times of restarting machine.

唔。。

题目要求重启次数最少,即是说想要需要的模式总数最少。

就是说想要用最少的模式完成所有的任务

每个任务可以被A,B两台机器的两种模式分别完成

“最少的什么什么”“完成/覆盖什么什么”“两种”

关键字已经出来了,二分图的最小点覆盖

每个任务让A的模式对B的模式连边,这样就是一个二分图,求一个最大匹配即最小点覆盖就好

需要注意的是,我们求出的是最少的模式数,如果其中包含了0模式那么答案就要减1,因为一开始就是0模式,不需要额外重启

完整代码:

#include<stdio.h>
#include<cstring>
using namespace std;

struct edge
{
int v,last;
}ed[400010];

int n,m,K,num=0,ans=0,tot=0;
int head[100010],book[100010],match[100010];

void add(int u,int v)
{
num++;
ed[num].v=v;
ed[num].last=head[u];
head[u]=num;
}

int dfs(int u)
{
for(int i=head[u];i;i=ed[i].last)
{
int v=ed[i].v;
if(book[v]!=tot)
{
book[v]=tot;
if(!match[v] || dfs(match[v]))
{
match[u]=v,match[v]=u;
return 1;
}
}
}
return 0;
}

void init()
{
memset(match,0,sizeof(match));
memset(head,0,sizeof(head));
memset(book,0,sizeof(book));
num=ans=tot=0;
}

int main()
{
while(1)
{
init();
scanf("%d",&n);
if(!n) break ;
scanf("%d%d",&m,&K);
while(K--)
{
int x,u,v;
scanf("%d%d%d",&x,&u,&v);
add(u,v+n),add(v+n,u);
}
for(int i=0;i<n+m;i++)
{
tot++;
if(!match[i]) ans+=dfs(i);
}
if(match[0]) ans--;
if(match
) ans--;
if(match[0]==n) ans++;
printf("%d\n",ans);
}
return 0;
}
/*
EL PSY CONGROO
*/


嗯,就是这样
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: