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;
}

posted on 2016-03-04 15:27  wuyuhan  阅读(200)  评论(0编辑  收藏  举报

导航