BZOJ 2502: 清理雪道
BZOJ 2502: 清理雪道
标签(空格分隔): OI-BZOJ OI-最小流 OI-上下界网络流
Time Limit: 10 Sec
Memory Limit: 128 MB
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福建集训
Solution####
有上下界网络流,弧的下界为1,求最小流
Code####
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
int read()
{
int s=0,f=1;char ch=getchar();
while(!('0'<=ch&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
return s*f;
}
int S,T,SS,TT,n,m,np;
int A[105],B[105],jr[10005],jc[10005];
int be[100005],bn[200005],bv[200005],bl[200005],bw=1;
void put(int u,int v,int l)
{bw++;bn[bw]=be[u];be[u]=bw;bv[bw]=v;bl[bw]=l;}
int d[100005];
bool spfa(int S,int T)
{
for(int i=1;i<=np;i++)
d[i]=10000000;
d[S]=1;
queue<int>q;
for(q.push(S);!q.empty();)
{int u=q.front();q.pop();
for(int i=be[u],v;i;i=bn[i])
if(d[v=bv[i]]>d[u]+1&&bl[i])
{d[v]=d[u]+1;
q.push(v);
}
}
return d[T]!=10000000;
}
int ans;
int dinic(int u,int mf,int T)
{
if(mf==0)return 0;
if(u==T)return mf;
int sum=0;
for(int i=be[u],v;i;i=bn[i])
if(d[v=bv[i]]==d[u]+1)
{int f=dinic(v,min(mf-sum,bl[i]),T);
bl[i]-=f;
bl[i^1]+=f;
sum+=f;
}
return sum;
}
bool p[101][101];
int main()
{
n=read();
S=++np,T=++np;
for(int i=1;i<=n;i++)
A[i]=++np,
put(S,A[i],1000000),
put(A[i],S,0),
put(A[i],T,1000000),
put(T,A[i],0);
for(int i=1;i<=n;i++)
{int m=read();
for(int j=1,v;j<=m;j++)
v=read(),
put(A[i],A[v],1e9),
put(A[v],A[i],0),
jc[A[i]]++,jr[A[v]]++;
}
SS=++np,TT=++np;
int sumr=0;
for(int i=1;i<=np;i++)
{if(jr[i]-jc[i]>0)put(SS,i,jr[i]-jc[i]),put(i,SS,0),sumr+=jr[i]-jc[i];
else put(i,TT,jc[i]-jr[i]),put(TT,i,0);
}
put(T,S,1e9);
put(S,T,0);
while(spfa(SS,TT))ans+=dinic(SS,1e9,TT);
if(ans<sumr)
{printf("-1\n");return 0;}
ans=bl[bw];
bl[bw]=bl[bw-1]=0;
while(spfa(T,S))ans-=dinic(T,1e9,S);
printf("%d\n",ans);
return 0;
}