题解:P14832 [THUPC 2026 初赛] Unpair Ampere
yangzichen1203 · · 题解
网络流好题。
需要代价最小使得条件不成立,想到最小割。
以下设
考虑怎么表示限制。对于一条链
又发现如果一个
最后在答案减去
边数是
:::success[Code]
#include<bits/stdc++.h>
#define For(i,j,k) for(int i=(j);i<=(k);i++)
#define dFor(i,j,k) for(int i=(j);i>=(k);i--)
using namespace std;
#define inf (1<<30)
#define D (1<<20)
class Dinic{
private:
struct Edge{
int to,rev;
int cap;
};
int n;
vector<vector<Edge>> g;
vector<int> dis,it;
bool bfs(int s,int t){
fill(dis.begin(),dis.end(),0);
queue<int> q;
dis[s]=1;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
for(auto &e:g[u]){
if(!dis[e.to]&&e.cap>0){
dis[e.to]=dis[u]+1;
q.push(e.to);
}
}
}
return dis[t]!=0;
}
int dfs(int u,int t,int f){
if(u==t) return f;
for(int &i=it[u];i<(int)g[u].size();i++){
Edge &e=g[u][i];
if(e.cap<=0) continue;
if(dis[e.to]!=dis[u]+1) continue;
int push=dfs(e.to,t,min(f,e.cap));
if(push>0){
e.cap-=push;
g[e.to][e.rev].cap+=push;
return push;
}
}
return 0;
}
public:
Dinic(int n=0):n(n){
g.assign(n+1,{});
dis.assign(n+1,{});
it.assign(n+1,{});
}
void add(int u,int v,int w){
int szu=g[u].size(),szv=g[v].size();
g[u].push_back({v,szv,w});
g[v].push_back({u,szu,0});
}
int maxflow(int s,int t){
int flow=0;
while(bfs(s,t)){
fill(it.begin(),it.end(),0);
while(1){
int push=dfs(s,t,inf);
if(!push) break;
flow+=push;
}
}
return flow;
}
};
#define MAXN 5005
int n,m;
int d[MAXN],a[MAXN];
vector<int> e[MAXN];
int in[MAXN];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin>>n>>m;
Dinic dinic(n*2+2);
int S=n*2+1,T=n*2+2;
For(i,1,n){
cin>>d[i];
}
int cnt=0;
For(i,1,n){
cin>>a[i];
if(d[i]==-1){
dinic.add(i,i+n,a[i]);
}else if(d[i]==0){
dinic.add(S,i,a[i]+D);
dinic.add(i+n,T,D);
dinic.add(i,i+n,inf);
cnt++;
}else{
dinic.add(i+n,T,a[i]+D);
dinic.add(S,i,D);
dinic.add(i,i+n,inf);
cnt++;
}
}
For(i,1,m){
int u,v;
cin>>u>>v;
dinic.add(u,v,inf);
dinic.add(v+n,u+n,inf);
}
cout<<dinic.maxflow(S,T)-D*cnt<<endl;
return 0;
}
:::