题目背景
赛时答疑:https://www.luogu.org/discuss/show/47581
在进入中忍考试的最后阶段,鸣人进行了自己修炼,为的就是迎战“天才忍者”——日向宁次……
中忍考试开始了,第一场:
漩涡鸣人 —— VS—— 日向宁次
题目描述
宁次是日向一族的人,日向一族拥有白眼和柔拳的力量,白眼可以透视看到对手的穴位和查克拉流动,而柔拳可以封锁对方的穴位,让查克拉无法经过。现在日向宁次打算用柔拳封锁鸣人的查克拉流动。
鸣人有n个穴位,而查克拉从k1个地方流出,从k2个地方释放以发动忍术,有m条查克拉单向管道可以运输查克拉。现在宁次要封锁鸣人的穴位,使查克拉无法从可以从发动忍术的地方释放。不过宁次需要考虑击中对方穴位的难度,他已经估量出了击中每个穴位的难度。
现在需要在难度最低的境况下封锁所有可以释放查克拉的穴位。
输入输出格式
输入格式:第一行两个数n,m。
接下来一行n个数表示击中穴位的难度
接下来m行两个个数分别表示在两个穴位之间有一条单向查克拉管道
接下来两个数k1,k2。
接下来一行k1个数表示查克拉灌入的穴位
接下来一行k2个数表示查克拉释放的穴位
输出格式:一行,表示最低的难度值
输入输出样例
输入样例#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
说明
样例1的解释:
数据点 | 数据范围 |
---|---|
约16%的数据 | 1≤n≤100,1≤m≤2001≤n≤100,1≤m≤200 |
约33%的数据 | 1≤n≤2000,1≤m≤50001≤n≤2000,1≤m≤5000 |
约50%的数据 | 1≤n≤7000,1≤m≤200001≤n≤7000,1≤m≤20000 |
约66%的数据 | 1≤n≤10000,1≤m≤300001≤n≤10000,1≤m≤30000 |
对于另约16%的数据 | n=10000,m=30000n=10000,m=30000 |
约100%的数据 | 1≤n≤10000,1≤m≤30000,1≤k1+k2≤n,1≤1≤n≤10000,1≤m≤30000,1≤k1+k2≤n,1≤ 难度值 ≤10000≤10000 |
大佬做的网络流%%%%
// 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;
}//