2502: 清理雪道
Time Limit: 10 Sec
Memory Limit: 128 MB
Submit: 510
Solved: 276
[ Submit][ Status][ Discuss]
Description
滑雪场坐落在
FJ
省西北部的若干座山上。
从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向。
你的团队负责每周定时清理雪道。你们拥有一架直升飞机,每次飞行可以从总部带一个人降落到滑雪场的某个地点,然后再飞回总部。从降落的地点出发,这个人可以顺着斜坡向下滑行,并清理他所经过的雪道。
由于每次飞行的耗费是固定的,为了最小化耗费,你想知道如何用最少的飞行次数才能完成清理雪道的任务。
Input
输入文件的第一行包含一个整数
n
(2 <= n <= 100) –
代表滑雪场的地点的数量。接下来的
n
行,描述
1~n
号地点出发的斜坡,第
i
行的第一个数为
mi
(0 <= mi < n)
,后面共有
mi
个整数,由空格隔开,每个整数
aij
互不相同,代表从地点
i
下降到地点
aij
的斜坡。每个地点至少有一个斜坡与之相连。
Output
输出文件的第一行是一个整数
k
–
直升飞机的最少飞行次数。
Sample Input
8
1 3
1 7
2 4 5
1 8
1 8
0
2 6 5
0
Sample Output
4
HINT
Source
#include
#include
#include
#include
#include
#define N 120
#define M 100003
using namespace std;
int n,m,x,tot=-1;
int point[M],du[N],deep[M],cur[M],maxflow;
int next[M*2],remain[M*2],v[M*2],s,t,ss,tt;
const int inf=1e9;
void add(int x,int y,int z)
{
tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=z;
tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;
}
bool bfs(int s,int t)
{
for (int i=1;i<=t;i++) cur[i]=point[i];
memset(deep,0x7f,sizeof(deep));
deep[s]=0;
queue p; p.push(s);
while (!p.empty())
{
int now=p.front(); p.pop();
for (int i=point[now];i!=-1;i=next[i])
if (deep[v[i]]>inf&&remain[i])
deep[v[i]]=deep[now]+1,p.push(v[i]);
}
if (deep[t]>inf) return false;
return true;
}
int dfs(int now,int t,int limit)
{
if (now==t||!limit) return limit;
int flow=0,f;
for (int i=cur[now];i!=-1;i=next[i])
{
cur[now]=i;
if (deep[v[i]]==deep[now]+1&&(f=dfs(v[i],t,min(remain[i],limit))))
{
limit-=f;
flow+=f;
remain[i]-=f;
remain[i^1]+=f;
if (!limit) break;
}
}
return flow;
}
void dinic(int s,int t)
{
maxflow=0;
while (bfs(s,t))
maxflow+=dfs(s,t,inf);
}
int main()
{
tot=-1;
memset(point,-1,sizeof(point));
memset(next,-1,sizeof(next));
scanf("%d",&n);
s=n+1; t=s+1; ss=t+1; tt=ss+1;
for (int i=1;i<=n;i++)
{
scanf("%d",&m);
for (int j=1;j<=m;j++)
{
scanf("%d",&x);
du[i]--; du[x]++;
add(i,x,inf);
}
}
for (int i=1;i<=n;i++)
{
add(s,i,inf);
add(i,t,inf);
if (du[i]>0) add(ss,i,du[i]);
if (du[i]<0) add(i,tt,-du[i]);
}
dinic(ss,tt);
add(t,s,inf);
dinic(ss,tt);
printf("%d\n",maxflow);
}