1 条题解

  • 0
    @ 2026-5-13 8:08:37

    没有直接购买的话就是一个经典的最大权闭合子图问题,现在考虑加入了直接购买这个操作之后怎么建模。

    对应的,一个技术的限制可以描述为:若这个技术是被研发的,则需要研发其所有后续技术(最大权闭合子图);若这个技术是被购买的,则对其后续技术无限制。

    设与 SS 联通表示选了,与 TT 联通表示没选。运用一点差分建图的思路,我们可以把每个技术 ii 拆成 ini,outiin_i,out_i,记 d=fihid=f_i-h_i,有:

    • d>0d>0,则我们连边 iniTin_i \rightarrow T,边权为 hih_iinioutiin_i \rightarrow out_i,边权为 fihif_i-h_i,这表示我们可以割掉前一个边(研发)或者同时割掉两个(购买),来使得 iiTT 不联通。此时后者可以保证对后续,即 outiout_i 之后没有限制。

    • d0d\leq 0,此时一定不会研发这个技术(直接买一定不劣),所以可以直接去掉 inioutiin_i \rightarrow out_i 的边,把 iniTin_i \rightarrow T 边的边权改为 fif_i,表示研发的费用即可。

    剩下的就是把所有商品 pp 到技术 ii 的边改为 pinip\rightarrow in_i,所有技术 ii 到技术 jj 的边改为 outiinjout_i \rightarrow in_j,跑最大权闭合子图即可。

    #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
    上传者