1 条题解
-
0
没有直接购买的话就是一个经典的最大权闭合子图问题,现在考虑加入了直接购买这个操作之后怎么建模。
对应的,一个技术的限制可以描述为:若这个技术是被研发的,则需要研发其所有后续技术(最大权闭合子图);若这个技术是被购买的,则对其后续技术无限制。
设与 联通表示选了,与 联通表示没选。运用一点差分建图的思路,我们可以把每个技术 拆成 ,记 ,有:
-
若 ,则我们连边 ,边权为 ;,边权为 ,这表示我们可以割掉前一个边(研发)或者同时割掉两个(购买),来使得 与 不联通。此时后者可以保证对后续,即 之后没有限制。
-
若 ,此时一定不会研发这个技术(直接买一定不劣),所以可以直接去掉 的边,把 边的边权改为 ,表示研发的费用即可。
剩下的就是把所有商品 到技术 的边改为 ,所有技术 到技术 的边改为 ,跑最大权闭合子图即可。
#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define pii pair<int,int> #define pll pair<long long,long long> #define i28 __int128 #define fir first #define INF (1e15) #define sec second #define pb push_back #define eb emplace_back const int N=1000+9,M=1e5+9; const int MOD=1e9+7,base=251; const double eps=1e-14; inline void chkmax(int &x,int y){x=x<y?y:x;} inline void chkmin(int &x,int y){x=x<y?x:y;} inline void chkmax(ll &x,ll y){x=x<y?y:x;} inline void chkmin(ll &x,ll y){x=x<y?x:y;} inline int lowbit(int x){return x&(-x);} int qpow(int a,int b,int p){ int ret=1; while(b){ if(b&1) ret=1ll*ret*a%p; a=1ll*a*a%p; b>>=1; } return ret; } #define int long long struct Dinic{ #define MAXN 1000000+9 #define MAXM 1000000+9 int n,s,t; int head[MAXN],tot=1; //remember to reset the tot int nxt[MAXM],to[MAXM],w[MAXM]; void add2(int u,int v,int x){ nxt[++tot]=head[u]; head[u]=tot; to[tot]=v; w[tot]=x; } void add(int u,int v,int x){ add2(u,v,x); add2(v,u,0); } int dep[MAXN],cur[MAXN]; queue<int> q; bool bfs(){ for(int i=1;i<=n;++i) dep[i]=0; for(int i=1;i<=n;++i) cur[i]=head[i]; // 1-index dep[s]=1; q.push(s); while(!q.empty()){ int u=q.front(); q.pop(); for(int i=head[u];i;i=nxt[i]){ if(!dep[to[i]] && w[i]){ dep[to[i]]=dep[u]+1; q.push(to[i]); } } } return dep[t]; } int dfs(int u,int flow){ if(u==t) return flow; int out=0; for(int i=cur[u];i && flow;i=nxt[i]){ cur[u]=i; if(w[i] && dep[to[i]]==dep[u]+1){ int x=dfs(to[i],min(flow,w[i])); flow-=x; out+=x; w[i]-=x; w[i^1]+=x; } } return out; } int solve(){ int ans=0; while(bfs()) ans+=dfs(s,INF); return ans; } } G; int n,m,p,q,f[N],h[N],g[N],tot,sum; void Mian(){ cin>>n>>m>>p>>q; for(int i=1;i<=n;++i) cin>>f[i]; for(int i=1;i<=n;++i) cin>>h[i]; for(int i=1;i<=m;++i) cin>>g[i]; tot=n*2+m; G.s=++tot; G.t=++tot; for(int i=1;i<=m;++i){ G.add(G.s,n*2+i,g[i]); sum+=g[i]; } for(int i=1;i<=p;++i){ int u,v; cin>>u>>v; G.add(n*2+v,u,INF); } for(int i=1;i<=q;++i){ int u,v; cin>>u>>v; G.add(v+n,u,INF); } for(int i=1;i<=n;++i){ int val=f[i]-h[i]; if(val>0){ G.add(i,G.t,h[i]); G.add(i,i+n,f[i]-h[i]); } else G.add(i,G.t,f[i]); } G.n=tot; cout<<sum-G.solve(); } void Mianclr(){ } signed main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); //freopen("P10544_3.in","r",stdin); //freopen("P10544_3.op","w",stdout); int c,T=1; //cin>>T; while(T--){ Mian(); Mianclr(); } } -
- 1
信息
- ID
- 7425
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者