bzoj 2502: 清理雪道

来源:互联网 发布:什么软件识别歌曲 编辑:程序博客网 时间:2024/06/10 05:24

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

2011福建集训


#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#define N 120#define M 100003using 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<int> 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);}



0 0