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

你可能感兴趣的:(BZOJ 2502: 清理雪道)