bzoj 2502(有上下界的最小流)

2502: 清理雪道

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 508   Solved: 274
[ 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


解题思路:看了po姐的建图,发现和我不一样,然后再看题目才知道是每一边都要经过。。。

我终于会打有上下界的网络流了。。。。



#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,len,S,T,TT,SS,ans;
const int INF=0x7fffffff;
int to[25000],next[25000],h[25000],zhi[25000];
int dis[250],q[300000];
int degree[250];


inline int read()
{
char y; int x=0,f=1;y=getchar();
while (y<'0' || y>'9') {if (y=='-') f=-1; y=getchar();}
while (y>='0'&&y<='9') {x=x*10+int(y)-48; y=getchar();}
    return x*f;
}


void ins(int x,int y,int flow)
 { 
  ++len; to[len]=y; next[len]=h[x]; zhi[len]=flow; h[x]=len;
 }


void insert(int x,int y,int flow)
 {
  ins(x,y,flow);
  ins(y,x,0);
 }


bool bfs()
 {
    memset(dis,-1,sizeof(dis)); dis[S]=0; int tail=1,head=0; q[tail]=S;
while (head<tail)
{
++head;
int u=h[q[head]];
while (u!=0)
{
if (zhi[u]>0 && dis[to[u]]==-1)
{
dis[to[u]]=dis[q[head]]+1;
++tail; q[tail]=to[u];
  }
u=next[u];
}
}
if (dis[T]!=-1) return true;else return false;
 }


int dicnic(int now,int sum)
 {
  if (now==T)return sum;
  int sug=0;
  int u=h[now];
  while (u!=0)
  {
  if (zhi[u]>0&&dis[to[u]]==dis[now]+1)
  {
  int s=dicnic(to[u],min(sum-sug,zhi[u]));
  if (s)
  {
  zhi[u]-=s; zhi[u^1]+=s;
  sug+=s;
  if (sug==sum)return sug;
}
 }
u=next[u];
 }
if (sug==0)dis[now]=-1; return sug;
 }


void getans()
 {
  int u=h[S];
  while (u!=0)
  {
     zhi[u]=0; zhi[u^1]=0;
  u=next[u];
}
u=h[T];
while (u!=0)
{
zhi[u]=0; zhi[u^1]=0;
u=next[u];
}
u=h[TT];
while (u!=0)
{
if (to[u]==SS)
{
ans=zhi[u^1];
zhi[u]=0; zhi[u^1]=0;
}
u=next[u];
}
 }


int main()
{
n=read(); len=1;
S=2*n+1; T=2*n+2; SS=2*n+3; TT=2*n+4;
for (int i=1;i<=n;++i)
{
insert(SS,i,INF);
insert(i,TT,INF);
   int x=read(); 
   for (int j=1;j<=x;++j)
    {
    int y=read();
       --degree[i]; 
       ++degree[y];
    insert(i,y,INF);
}
}
for (int i=1;i<=n;++i)
{
if(degree[i]>0)
            insert(S,i,degree[i]);
        if(degree[i]<0)
            insert(i,T,-degree[i]);
}
insert(TT,SS,INF);
while (bfs())
{
dicnic(S,0x7fffffff);
}
getans();
insert(S,TT,INF);
insert(SS,T,INF);
while (bfs())
{
ans-=dicnic(S,0x7fffffff);
}
printf("%d",ans);
}

你可能感兴趣的:(bzoj 2502(有上下界的最小流))