您的位置:首页 > 大数据 > 人工智能

HDU 5352 MZL's City (2015 Multi-University Training Contest 5)

2015-08-04 23:23 567 查看

题目大意:

一个地方的点和道路在M年前全部被破坏,每年可以有三个操作, 1.把与一个点X一个联通块内的一些点重建,2.连一条边,3.地震震坏一些边,每年最多能重建K个城市,问最多能建多少城市,并输出操作要让字典序最小

思路:

trivial:显然每年向当年可以建的城市连边,每年可以匹配最多K个城市,嗯,很明显的网络流思路,可这样方案数不太好输出

full:再仔细想想这就是多对一的多重匹配,跑一跑匈牙利就可以,K个城市可以拆点,当然简单的方法直接跑K次也可以(想一想为什么)

为了字典序最小,我们要尽量让后面的点匹配,所以从后往前跑匹配就可以

// i love zxr
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 10009
using namespace std;
int matrix[209][209];
int nex[maxn],head[maxn],point[maxn],now;
int mark[maxn],deg[maxn],ans[maxn];
int visit[maxn],x,y,match[maxn],o,p,n,m,k,h
;
void add(int x,int y)
{
nex[++now] = head[x];
head[x] = now;
point[now] = y;
}

int dfs1(int k,int year)
{
visit[k]=1;
add(year,k);
for(int i=1;i<=n;i++)if(matrix[k][i]==1 && !visit[i])dfs1(i,year);
}

int dfs(int k)
{
for(int i=head[k];i;i=next[i])
{
int u = point[i];
if(visit[u])continue;
visit[u]=1;
if(match[u]==-1 || dfs(match[u]))
{
match[u] = k;
return 1;
}
}
return 0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
h=0;
memset(matrix,0,sizeof(matrix));
memset(head,0,sizeof(head));
memset(mark,0,sizeof(mark));
now=0;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++)
{
scanf("%d",&o);
if(o==1)
{
scanf("%d",&x);
memset(visit,0,sizeof(visit));
dfs1(x,i);
mark[i]=1;
}
if(o==2)
{
scanf("%d%d",&x,&y);
matrix[x][y] = 1;
matrix[y][x] = 1;
}
if(o==3)
{
scanf("%d",&p);
for(int i=1;i<=p;i++)
{
scanf("%d%d", &x, &y);
matrix[x][y] = 0;
matrix[y][x] = 0;
}
}
}
int an=0;
memset(match,-1,sizeof(match));
for(int i=m;i>=1;i--)if(mark[i])
{
int u =0;
for(int j=1;j<=k;j++)
{
memset(visit,0,sizeof(visit));
if(dfs(i))u++;
}
an+=u;
ans[++h]=u;
}
printf("%d\n",an);
for(int i=h;i>=2;i--)
{
printf("%d ",ans[i]);
}
if(h)printf("%d\n",ans[1]);
}
return 0;
}

 

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