• [网络流24题]太空飞行计划问题(最小割)


    题意

    给定n个实验,m个机器,选一个实验得到ai价值,选一个机器有bi代价,每一个实验必须要某些机器参与才能进行,问获得的最大价值

    思路

    对于每一个实验,分为两种选择:

    1. 选取这个实验,那么必须选取其对应的所有机器

    2. 不选这个实验,那么其对应的机器只受到其他实验选择的影响

    也就是说在实验和机器中选择一部分“放弃”,使得总价值最大,考虑最小割

    建两排点分别表示实验和机器,用权值为ai的边连接源点与实验,权值为bi的边连接机器与汇点,实验与其相关的机器连权值为INF的边,那么ans=sigma(ai)-最小割

    通过这样建图就可以发现,由于中间连边为INF不可能被切掉,所以被切掉的边只能是实验或者它对应的所有机器

    由于原题还需要输出方案,只需要输出最后一次bfs(即没有増广路)可以到达的实验以及其对应的机器即可

    Code:

    #include<bits/stdc++.h>
    #define N 105
    using namespace std;
    const int INF = 2000000000;
    int n,m,s=101,t=102,sum;
    bool flag;
    int dep[N];
    struct Edge
    {
    	int next,to,flow;
    }edge[10005];int head[N],cur[N],cnt=1;
    void add_edge(int from,int to,int flow)
    {
    	edge[++cnt].next=head[from];
    	edge[cnt].to=to;
    	edge[cnt].flow=flow;
    	head[from]=cnt;
    }
    void add(int from,int to,int flow)
    {
    	add_edge(from,to,flow);
    	add_edge(to,from,0); 
    }
    int read()
    {
        char ch=' ';int res=0;
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) res=res*10+ch-'0',ch=getchar();
        if(ch=='
    ') flag=1;
        return res;
    }
    bool bfs()
    {
    	queue<int> q;
    	memset(dep,0,sizeof(dep));
    	for(int i=1;i<=104;++i) cur[i]=head[i];
    	q.push(s); dep[s]=1;
    	while(!q.empty())
    	{
    		int u=q.front();q.pop();
    		for(int i=head[u];i;i=edge[i].next)
    		{
    			int v=edge[i].to;
    			if(edge[i].flow<=0||dep[v]) continue;
    			dep[v]=dep[u]+1;
    			q.push(v);
    			if(v==t) return true;
    		}
    	}
    	return false;
    }
    int dfs(int rt,int rest)
    {
    	if(rt==t) return rest;
    	int used=0;
    	for(int i=cur[rt];i;i=edge[i].next)
    	{
    		cur[rt]=i;
    		int v=edge[i].to;
    		if(dep[v]==dep[rt]+1&&edge[i].flow>0)
    		{
    			int k=dfs(v,min(edge[i].flow,rest-used));
    			if(!k) dep[v]=0;
    			edge[i].flow-=k;
    			edge[i^1].flow+=k;
    			used+=k;
    		}
    	}
    	return used;
    }
    int dinic()
    {
    	int ret=0,flow=0;
    	while(bfs()) while((flow=dfs(s,INF))) ret+=flow;
    	return ret;
    }
    int main()
    {
    	n=read();m=read();
    	for(int i=1;i<=n;++i)
    	{
    		int earn=read();flag=0;
    		sum+=earn;
    		add(s,i,earn);
    		while(!flag)
    		{
    			int ned=read();
    			add(i,ned+50,INF);
    		}
    	}
    	for(int i=1;i<=m;++i)
    	{
    		int cost=read();
    		add(i+50,t,cost);
    	}
    	int maxx=dinic();
    	for(int i=1;i<=50;++i) if(dep[i]) printf("%d ",i);
    	printf("
    ");
    	for(int i=1;i<=50;++i) if(dep[i+50]) printf("%d ",i);
    	printf("
    ");
    	printf("%d
    ",sum-maxx);
    	return 0;
    }
    
  • 相关阅读:
    ref与out的区别(C#)
    用MS SQL Server 2008修改数据库表时提示“不允许保存更改”的解决方法
    测试的职责
    性能测试新手误区(三):用户数与压力
    JAVA + LR实现apache流媒体的性能测试(LR部分)
    性能测试新手误区(二):为什么我模拟的百万测试数据是无效的
    JAVA + LR实现apache流媒体的性能测试(JAVA部分)
    性能测试新手误区(六):性能监控
    性能测试新手误区(五):这是性能问题么
    性能测试新手误区(四):一切来自录制
  • 原文地址:https://www.cnblogs.com/Chtholly/p/11203688.html
Copyright © 2020-2023  润新知