您的位置:首页 > 其它

UVALive 4654 (最小路径覆盖)

2016-06-02 23:44 295 查看
题目链接:点击打开链接

题意:节点1有很多个机器人,给定一张图,机器人每次走到一个节点i都会收到i这个

指令。给出一个得到的指令序列,求最少和最多需要多少机器人才能完成这个序列。

最多的指令很简单,贪心扫一遍序列能够从1出发到达就从1出发,统计序列中这样的

节点数。

最少的指令可以这样建模。因为我们要完成序列里面的每一个指令,相当于是从1出发

的路径要覆盖所有的节点。而每一条路径对应一个从1出发的机器人,这样就转化为

了最小路径覆盖。根据二分图的性质最小路径覆盖=节点数-最大匹配。



#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define maxn 211
#define maxm maxn*maxn*2

bool mp[maxn][maxn];
int n, m;
int a[maxn];

struct node {
int u, v, next;
}edge[maxm];
int head[maxn], cnt;

void add_edge (int u, int v) {
edge[cnt].u = u, edge[cnt].v = v, edge[cnt].next = head[u], head[u] = cnt++;
}

int pre[maxn];
bool vis[maxn];

bool dfs (int u) {
for (int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].v;
if (!vis[v]) {
vis[v] = 1;
if (pre[v] == -1 || dfs (pre[v])) {
pre[v] = u;
return 1;
}
}
}
return 0;
}

int hungry () {
int ans = 0;
memset (pre, -1, sizeof pre);
for (int i = 1; i <= m; i++) {
memset (vis, 0, sizeof vis);
if (dfs (i))
ans++;
}
return m-ans;
}

void solve () {
int Max = 0;
for (int i = 1; i <= m; i++) {
if (mp[1][a[i]])
Max++;
}
for (int i = 1; i <= m; i++) {
for (int j = i+1; j <= m; j++) {
if (mp[a[i]][a[j]])
add_edge (i, j);
}
}
printf ("%d %d\n", hungry (), Max);
}

int main () {
while (cin >> n >> m && n+m) {
memset (head, -1, sizeof head);
cnt = 0;
memset (mp, 0, sizeof mp);
for (int i = 1; i <= n; i++) {
int c;
scanf ("%d", &c);
while (c--) {
int u;
scanf ("%d", &u);
mp[i][u] = 1;
}
}
for (int i = 1; i <= m; i++) {
scanf ("%d", &a[i]);
}
solve ();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: