T29389 中忍考试:宁次VS鸣人-白眼!

题目背景

赛时答疑:https://www.luogu.org/discuss/show/47581

在进入中忍考试的最后阶段,鸣人进行了自己修炼,为的就是迎战“天才忍者”——日向宁次……

中忍考试开始了,第一场:

漩涡鸣人 —— VS—— 日向宁次

题目描述

宁次

宁次是日向一族的人,日向一族拥有白眼和柔拳的力量,白眼可以透视看到对手的穴位和查克拉流动,而柔拳可以封锁对方的穴位,让查克拉无法经过。现在日向宁次打算用柔拳封锁鸣人的查克拉流动。

鸣人有n个穴位,而查克拉从k1个地方流出,从k2个地方释放以发动忍术,有m条查克拉单向管道可以运输查克拉。现在宁次要封锁鸣人的穴位,使查克拉无法从可以从发动忍术的地方释放。不过宁次需要考虑击中对方穴位的难度,他已经估量出了击中每个穴位的难度。

现在需要在难度最低的境况下封锁所有可以释放查克拉的穴位。

输入输出格式

输入格式:

第一行两个数n,m。

接下来一行n个数表示击中穴位的难度

接下来m行两个个数分别表示在两个穴位之间有一条单向查克拉管道

接下来两个数k1,k2。

接下来一行k1个数表示查克拉灌入的穴位

接下来一行k2个数表示查克拉释放的穴位

输出格式:

一行,表示最低的难度值

输入输出样例

输入样例#1:  复制
5 10
59 7 44 1 44 
5 4
4 3
3 4
1 4
5 1
2 5
2 1
3 5
5 3
1 5
2 2
5 1 
3 2 
输出样例#1:  复制
44
输入样例#2:  复制
8 18
32 10 14 9999 67 13 23 47 
5 1
2 5
1 7
1 5
8 3
1 8
2 4
5 7
8 6
3 6
3 5
7 2
2 6
7 4
3 1
6 8
5 6
3 8
1 5
5 
1 4 3 6 8 
输出样例#2:  复制
67

说明

样例1的解释: 样例解释

数据点 数据范围
约16%的数据 1≤n≤100,1≤m≤2001n100,1m200
约33%的数据 1≤n≤2000,1≤m≤50001n2000,1m5000
约50%的数据 1≤n≤7000,1≤m≤200001n7000,1m20000
约66%的数据 1≤n≤10000,1≤m≤300001n10000,1m30000
对于另约16%的数据 n=10000,m=30000n=10000,m=30000
约100%的数据 1≤n≤10000,1≤m≤30000,1≤k1+k2≤n,1≤1n10000,1m30000,1k1+k2n,1 难度值 ≤1000010000
大佬做的网络流%%%%
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
const int maxn=30003;
const int st=0;
const int en=30002;
const int inf=2e9;
struct node
{
    int to,cap,rev;
};
vector<node>G[maxn];
int iter[maxn],level[maxn];
void add_edge(int from,int to,int cap)
{
    G[from].push_back((node){to,cap,G[to].size()});
    G[to].push_back((node){from,0,G[from].size()-1});
}
void bfs(int s)
{
    memset(level,-1,sizeof(level));
    queue<int>P;P.push(s);level[s]=0;
    while(!P.empty())
    {
        int v=P.front();P.pop();
        for(int i=0;i<G[v].size();i++)
        {
            node e=G[v][i];
            if(e.cap>0&&level[e.to]<0)
            {
                level[e.to]=level[v]+1;
                P.push(e.to);
            }
        }
    }
}
int dfs(int v,int t,int f)
{
    if(v==t)return f;
    for(int &i=iter[v];i<G[v].size();i++)
    {
        node &e=G[v][i];
        if(e.cap>0&&level[e.to]>level[v])
        {
            int d=dfs(e.to,t,min(f,e.cap));
            if(d>0)
            {
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}
int max_flow(int s,int t)
{
    int flow=0;
    while(1)
    {
        bfs(s);
        if(level[t]<0) return flow;
        memset(iter,0,sizeof(iter));
        int f;
        while((f=dfs(s,t,inf))>0) flow+=f;
    }
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        int x;scanf("%d",&x);
        add_edge(i,i+n,x);
    }
    while(m--)
    {
        int x,y;scanf("%d%d",&x,&y);
        add_edge(x+n,y,inf);
    }
    int T1,T2; scanf("%d%d",&T1,&T2);
    while(T1--)
    {
        int s;scanf("%d",&s);
        add_edge(st,s,inf);
    }
    while(T2--)
    {
        int s;scanf("%d",&s);
        add_edge(s+n,en,inf);
    }
    printf("%d\n",max_flow(st,en));
    return 0;
}//




猜你喜欢

转载自blog.csdn.net/ant_e_zz/article/details/80958475
今日推荐