P4843 清理雪道 上下界网络流

  

题目描述

滑雪场坐落在FJ省西北部的若干座山上。

从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向。

你的团队负责每周定时清理雪道。你们拥有一架直升飞机,每次飞行可以从总部带一个人降落到滑雪场的某个地点,然后再飞回总部。从降落的地点出发,这个人可以顺着斜坡向下滑行,并清理他所经过的雪道。

由于每次飞行的耗费是固定的,为了最小化耗费,你想知道如何用最少的飞行次数才能完成清理雪道的任务。

输入格式

输入文件的第一行包含一个整数n (2 <= n <= 100) – 代表滑雪场的地点的数量。

接下来的n行,描述1~n号地点出发的斜坡,第i行的第一个数为mi (0 <= mi < n) ,后面共有mi个整数,由空格隔开,每个整数aij互不相同,代表从地点i下降到地点aij的斜坡。每个地点至少有一个斜坡与之相连。

输出格式

输出文件的第一行是一个整数k – 直升飞机的最少飞行次数。

输入输出样例

输入 #1
8
1 3
1 7
2 4 5
1 8
1 8
0
2 6 5
0
输出 #1
4


建立超级源点和超级汇点 超级源点像每个点连inf 每个点像超级汇点连inf 两个点之间如果能到达那么连边(如果可以保证这条边的流量至少为1的话 跑出最小流 显然就是这题的答案)

套上有源汇最小流模板即可
#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3f
const int N=4e3+44;
const int M=4e4+54;
int d[N];
struct edge {
    int to, next, w;
} e[M << 1];
int head[N],cur[N],cnt = 1;
void add(int x, int y, int z) {
    e[++cnt] = (edge){y, head[x], z};
    head[x] = cnt;
    e[++cnt] = (edge){x, head[y], 0};
    head[y] = cnt;
}
void ins(int x,int y,int a,int b)
{
    add(x,y,b-a);
    d[x]-=a;
    d[y]+=a;
}
int level[N];
bool bfs(int s, int t) {
    memset(level, 0, sizeof level);
    queue<int> q;
    level[s] = 1;
    q.push(s);
    while (!q.empty()) {
        int pos = q.front();q.pop();
        for (int i = head[pos]; i; i = e[i].next) {
            int nx = e[i].to;
            if (!e[i].w || level[nx]) continue;
            level[nx] = level[pos] + 1;
            q.push(nx);
        }
    }
    return level[t];
}
int dfs(int s, int t, int flow) {
    if(s==t||flow==0)return flow;

    int f,ret = 0;
    for (int &i = cur[s],v; i; i = e[i].next) {
         v = e[i].to;
        if (level[v] == level[s] + 1 && (f=dfs(v,t,min(flow,e[i].w)))>0) {
            e[i].w -= f;
            e[i ^ 1].w += f;
            flow -= f;
            ret += f;
            if(!flow)break;
        }
    }
    return ret;
}
int dinic(int s, int t) {
    int ret = 0;
    while (bfs(s, t)) memcpy(cur,head,sizeof cur),ret += dfs(s, t, inf);
    return ret;
}
int n,m,s,t,a,b,c,sum,S,T;

int main()
{
    scanf("%d",&n);
    s=n+1,t=s+1;S=t+1,T=S+1;
    rep(i,1,n)
    {
        ins(s,i,0,inf);ins(i,t,0,inf);
        int k;scanf("%d",&k);
        while(k--)
        {
            int x;scanf("%d",&x);
            ins(i,x,1,inf);
        }
    }
    rep(i,1,n)
    if(d[i]>0)add(S,i,d[i]);
    else if(d[i]<0)add(i,T,-d[i]);

    dinic(S,T);
    add(t,s,inf);
    dinic(S,T);
    cout<<e[cnt].w;

    return 0;
}
View Code





猜你喜欢

转载自www.cnblogs.com/bxd123/p/11308059.html