省选专练[SDOI2017]新生舞会

我发现只要是带舞会二字的必然和网络流有关,原因是舞会会出现匹配问题。

然后证明了,当前各省省选的DAY2T1的难度大体就是分数规划套一个省选知识点的check函数,HAOI,SCOI,SDOI都有过。

然后这是标准分数规划模型

sigmaAi/sigmaBi=C

乘过来于是Ai-C*Bi=0;

当C较小的时候便大于0;

于是用费用流或者KMcheck一下就好了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
#define INF 1e18+120
inline void read(int &x){
	x=0;
	int f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
struct Front_star{
	int u,v,w,nxt;
	double c;
}e[40000*4+120];
double a[200][200]={0};
double b[200][200]={0};
int n;
int first[500]={0};
int cnt=1;
void addedge(int u,int v,int w,double c){
	cnt++;
	e[cnt].u=u;
	e[cnt].v=v;
	e[cnt].w=w;
	e[cnt].c=c;
	e[cnt].nxt=first[u];
	first[u]=cnt;
}
void add(int u,int v,int w,double c){
	addedge(u,v,w,c);
	addedge(v,u,0,-c);
}
int S=0;
int T=251;
void build(double ans){
	cnt=1;
	memset(first,0,sizeof(first));
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			add(i,j+n,1,a[i][j]-ans*b[i][j]);
		}
	}
	for(int i=1;i<=n;i++){
		add(S,i,1,0);
		add(i+n,T,1,0);
	}
}
queue<int> q;
double dis[500]={0};
int inqueue[500]={0};
int pre[500]={0};
bool SPFA(){
	for(int i=S;i<=T;i++){
		dis[i]=-INF;
		pre[i]=0;
	}
	dis[S]=0;
	q.push(S);
	while(!q.empty()){
		int x=q.front();
		q.pop();
		inqueue[x]=0;
		for(int i=first[x];i;i=e[i].nxt){
			int v=e[i].v;
			if(e[i].w&&dis[x]+e[i].c>dis[v]){
				pre[v]=i;
				dis[v]=dis[x]+e[i].c;
				if(!inqueue[v]){
					q.push(v);
					inqueue[v]=1;
				}
			}
		}
	}
	return dis[T]!=-INF;
}
bool check(){
	double ans=0;
	while(SPFA()){
		int s=int(1e9+7);
		for(int i=pre[T];i;i=pre[e[i^1].v]){
			s=min(s,e[i].w);
		}
		for(int i=pre[T];i;i=pre[e[i^1].v]){
			e[i].w-=s;
			e[i^1].w+=s;
		}
		ans+=s*dis[T];
//		cout<<"ans= "<<ans<<endl;
	}
	if(ans>0){
		return true;
	} 
	else{
		return false;
	}
}
int main(){
	read(n);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			int x;
			read(x);
			a[i][j]=(double)(x);
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			int x;
			read(x);
			b[i][j]=(double)x;
		}
	}
	double l=0;
	double r=1e4+7;
	double eps=0.0000001;
	double ans;
	while(r-l>eps){
		double mid=(l+r)/2;
		build(mid);
		if(check()){
			l=mid;
		}
		else{
			r=mid;
		}
//		printf("l=%.10lf r=%.10lf\n",l,r);
	}
	printf("%.6lf",l);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MT的森林舞会是一种编程语言,它的主要目的是帮助孩子们学习和理解编程的概念。它以一种图形化的方式呈现,通过拖动和连接不同的积木块来创建程序。MT的森林舞会为孩子们提供了一个有趣而富有想象力的环境,让他们能够探索和实践编程的基本原理。 MT的森林舞会的编程语言采用了简单明了的命令,例如“移动”、“跳跃”和“旋转”等。通过选择并组合这些命令,孩子们可以编写程序来指导角色在虚拟的森林舞会中进行各种活动。这些活动包括与其他角色的互动、收集物品和解决谜题等。 这种图形化的编程语言不仅使编程变得更易于理解和学习,还激发了孩子们的创造力和逻辑思维能力。他们可以根据自己的想法设计和探索不同的舞会场景,并通过调整命令的顺序和参数来改变角色的行为。 MT的森林舞会还提供了一个可视化的调试工具,帮助孩子们找出程序中的错误并进行修改。这样,他们能够学会分析问题、寻找解决方案,并进行自我纠错。这种及时的反馈和强调实践的学习方法,有助于培养孩子们的解决问题和团队合作的能力。 总之,MT的森林舞会的编程是一种以图形化方式呈现的编程语言,旨在引导孩子们学习和实践编程的基本原理。它通过创造有趣的森林舞会场景,培养孩子们的创造力、逻辑思维和解决问题的能力,为他们打开了编程的大门。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值