机器任务
有两台机器 A,B 以及 K 个任务。
机器 A 有 N 种不同的模式(模式 0∼N−1),机器 B 有 M 种不同的模式(模式 0∼M−1)。
两台机器最开始都处于模式 0。
每个任务既可以在 A 上执行,也可以在 B 上执行。
对于每个任务 i,给定两个整数 a[i] 和 b[i],表示如果该任务在 A 上执行,需要设置模式为 a[i],如果在 B 上执行,需要模式为 b[i]。
任务可以以任意顺序被执行,但每台机器转换一次模式就要重启一次。
求怎样分配任务并合理安排顺序,能使机器重启次数最少
最小点覆盖=最大匹配
从左部非匹配点出发增广路标记,取左部没有被标记的点 有部标记的点
2要素: 每个边两头必须选一头
读题: 最开始处于模式0
这种的解决方式应当是直接不建图 而不是在计算点覆盖的时候去掉
因为实际的点覆盖可能选了和0模式相连的点 而这种是直接选择0模式更好的 所以不合法
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
const int N=205;
const int M=2005;
int read()
{
int x=0,f=0,c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return f?-x:x;
}
struct Edge
{
int to,next;
}e[M];
int head[N],cnt;
void _add(int a,int b){ e[++cnt]=(Edge){b,head[a]}; head[a]=cnt;}
void add(int a,int b){
//cout<<a<<" "<<b<<endl;
_add(a,b); _add(b,a);}
bool tag[N],vis[N];
int match[N],n,m,k;
bool used[N];
void clean()//clean不能用memset
{
memset(match,0,sizeof match);
memset(head,0,sizeof head);
memset(used,0,sizeof used);
cnt=0;
}
bool dfs(int x)
{
tag[x]=1;
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].to;
if(vis[y]) continue; vis[y]=1; tag[y]=1;
if( !match[y] || dfs(match[y]) ){ match[y]=x;match[x]=y; return true;}
}
return false;
}
int main()
{
while(n=read())
{
clean();
m=read(); k=read();
for(int i=1;i<=k;i++)
{
int x=read(),a=read()+1,b=read()+1;
if(a==1||b==1) continue;
add(a,b+n);
used[a]=1; used[b+n]=1;
}
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof vis);
if(used[i]) dfs(i);
}
memset(tag,0,sizeof tag);
for(int i=1;i<=n;i++)
if(!match[i]&&used[i]) dfs(i);
int ans=0;
for(int i=2;i<=n;i++) if(!tag[i]&&used[i]) ans++;
for(int i=n+2;i<=n+m;i++) if(tag[i]&&used[i]) ans++;
printf("%d\n",ans);
}
return 0;
}
注意:多组数据不要用memset

浙公网安备 33010602011771号