zoukankan      html  css  js  c++  java
  • 雅礼集训2019 Day4

    雅礼集训2019 Day4

    大爷

    第一眼感觉是个线性规划的形式,两棵树一模一样的好像可以贪心

    [operatorname{maximize} sum_{i}^{n} x_iw_i\ operatorname{s.t.} left{ egin{aligned} sum_i x_iA_{i,1} = c_1\ cdots \ sum_i x_iA_{i,2n} = c_{2n} end{aligned} ight. \xgeq 0 \xleq 1 ]

    暴力单纯形肯定不行,想了一下这东西就继承贪心思路+费用流。s->第一棵树->第二棵树->t即可。

    具体建模方式:

    #include<bits/stdc++.h>
    #define FOR(i,a,b) for(register int i=(a);i<=(b);++i)
    using namespace std;
    int read(){
    	int x=0,pos=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
    	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    	return pos?x:-x; 
    } 
    const int N = 601;
    int n,m,rt1,rt2;
    const int inf = 1e9+7;
    struct node{
    	int v,nex,w,c;
    };
    int val[N];
    int s,t,tot;
    int mxf,totc;
    namespace dinic{
    	int head[N*4],cur[N*4];node edge[N*20];int top=1;
    	int dis[N*4],vis[N*4];
    	void add(int u,int v,int w,int c){
    		edge[++top].v=v;edge[top].nex=head[u];head[u]=top;edge[top].w=w;edge[top].c=c;
    		edge[++top].v=u;edge[top].nex=head[v];head[v]=top;edge[top].w=0;edge[top].c=-c;
    	}
    	int bfs(){
    		queue<int>q;
    		FOR(i,1,tot) dis[i]=inf,vis[i]=0;
    		dis[s]=0;q.push(s);
    		while(!q.empty()){
    			int now=q.front();q.pop();vis[now]=0;
    			for(int i=head[now];i;i=edge[i].nex){
    				int v=edge[i].v;
    				if(edge[i].w&&dis[v]>dis[now]+edge[i].c){
    					dis[v]=dis[now]+edge[i].c;
    					if(!vis[v]){
    						vis[v]=1;q.push(v);
    					}
    				}
    			}
    		}
    		return dis[t]<inf;
    	}
    	int dfs(int now,int flow){
    		int res=flow;
    		if(now==t||flow==0) return flow;
    		vis[now]=1;
    		for(int &i=cur[now];i;i=edge[i].nex){
    			int v=edge[i].v;
    			if(!vis[v]&&edge[i].w&&dis[v]==dis[now]+edge[i].c){
    				int nw=dfs(v,min(res,edge[i].w));
    				edge[i].w-=nw;edge[i^1].w+=nw;totc+=nw*edge[i].c;res-=nw;
    				if(!res) return flow;
    			}
    		}
    		vis[now]=0;
    		return flow-res;
    	}
    	void solve(){
    		while(bfs()){
    			memcpy(cur,head,sizeof cur);
    			mxf+=dfs(s,inf);
    		}
    	}
    }
    struct T{
    	int head[N];node edge[N*2];int top;
    	int a[N];int w[N];
    	vector<int>par[N];int tpe,flg;
    	T(){
    		FOR(i,1,N-1) a[i]=inf;
    		top=flg=0;tpe=1;
    	}
    	void add(int u,int v){
    		edge[++top].v=v;
    		edge[top].nex=head[u];
    		head[u]=top;
    	}
    	void dfs(int now,int pre,int tp){
    		par[tp].push_back(now);
    		for(int i=head[now];i;i=edge[i].nex){
    			int v=edge[i].v;
    			if(a[v]==inf) a[v]=0;
    			if(v==pre) continue;
    			if(a[v]){
    				w[tp]-=a[v];
    				if(w[tp]<0) return flg=1,void();
    				w[++tpe]=a[v];dfs(v,now,tpe);
    			}else{
    				dfs(v,now,tp);
    			}
    		}
    	}
    	void work(){
    		FOR(i,1,tpe){
    			int li=par[i].size();int vn=++tot;
    			dinic::add(s,vn,w[i],0);
    			for(int j=0;j<li;j++){
    				int v=par[i][j];
    				dinic::add(vn,v,1,-val[v]);
    			}
    		}
    	}
    	void work2(){
    		FOR(i,1,tpe){
    			int li=par[i].size();int vn=++tot;
    			dinic::add(vn,t,w[i],0);
    			for(int j=0;j<li;j++){
    				int v=par[i][j];
    				dinic::add(v,vn,1,0);
    			}
    		}
    	}
    }t1,t2;
    int main(){
    	freopen("w.in","r",stdin);
    	freopen("w.out","w",stdout);
    	n=read();rt1=read(),rt2=read();
    	FOR(i,1,n) val[i]=read();
    	FOR(i,1,n-1){
    		int u=read(),v=read();
    		t1.add(u,v);t1.add(v,u);
    	}
    	FOR(i,1,n-1){
    		int u=read(),v=read();
    		t2.add(u,v);t2.add(v,u);
    	}
    	int q0=read();
    	FOR(i,1,q0){
    		int x=read(),y=read();
    		t1.a[x]=min(t1.a[x],y);
    	}
    	int q1=read();
    	FOR(i,1,q1){
    		int x=read(),y=read();
    		t2.a[x]=min(t2.a[x],y);
    	}
    	s=n+1,t=n+2;tot=n+2;
    	t1.w[1]=t1.a[rt1];
    	t1.dfs(rt1,0,1);
    	if(t1.flg) {
    		printf("-1");return 0;
    	}
    	t1.work();
    	t2.w[1]=t2.a[rt2];
    	t2.dfs(rt2,0,1);
    	if(t2.flg) {
    		printf("-1");return 0;
    	}
    	t2.work2();
    	dinic::solve();
    	if(mxf==t1.a[rt1]&&mxf==t2.a[rt2]){
    		printf("%d",-totc);
    	}else{
    		printf("-1");
    	}
    	return 0;
    } 
    

    关于数据,我写了个python把subtask从文件夹里提出来好自动添加试题(没有cdf差评)

    import os
    import sys
    
    inn=0
    outn=0
    
    problemname='n'
    
    def getFileList(dir,mylist):
        global inn
        global outn
        global problemname
        for file in os.listdir(dir):
            file_path = os.path.join(dir,file) #绝对路径
            if os.path.isdir(file_path):
                getFileList(file_path,mylist)
            else:
                if(file_path.endswith('.in')):
                    inn+=1
                    os.system ("xcopy %s %s\%s%d.in /s /y /F" % (file_path, mylist, problemname, inn))
                else:
                    if(file_path.endswith('.ans')):
                        outn+=1
                        os.system ("xcopy %s %s\%s%d.out /s /y /F" % (file_path, mylist, problemname, outn))
    
    if __name__ == '__main__':
        mylist='E:lemon雅礼集训DAY4data\%s' %(problemname)
        getFileList(mylist,mylist)
    
    

    然而有些问题所以只能半自动。。。(要一直按F)(我不是加了/F吗?没用啊)

    熊猫

    容斥倒是可以容斥,转化成不能满足某些条件也跟容斥之前差不多...

    如果没有大小的限制,直接枚举00的段数,接在一段前面的就是10,接在后面的就是01,剩下的是11,边界情况讨论一下,乘上组合数

    那么再枚举一下可以无限制的长度,应该就能做(len^2),实现应该会很复杂

    也可以构建出自动机,然后就不会了

    题解:把枚举改成插板法,讨论略复杂

    鸽子

    第一次看以为是求任意折线上距离为定值的距离最小值,写了个三分,写完才发现这只是subtask4

    正解就是把上面的改一下,把m-1个区间重叠起来,二分答案然后检查有无一个点被覆盖m次即可。具体实现我是二分里先三分再二分,总复杂度(O(nlog^2n))。统计的话覆盖数=左端点-右端点,注意要卡常。

    总结:读题重要啊...

    #pragma GCC diagnostic error "-std=c++11"
    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #pragma GCC optimize("-fgcse")
    #pragma GCC optimize("-fgcse-lm")
    #pragma GCC optimize("-fipa-sra")
    #pragma GCC optimize("-ftree-pre")
    #pragma GCC optimize("-ftree-vrp")
    #pragma GCC optimize("-fpeephole2")
    #pragma GCC optimize("-ffast-math")
    #pragma GCC optimize("-fsched-spec")
    #pragma GCC optimize("unroll-loops")
    #pragma GCC optimize("-falign-jumps")
    #pragma GCC optimize("-falign-loops")
    #pragma GCC optimize("-falign-labels")
    #pragma GCC optimize("-fdevirtualize")
    #pragma GCC optimize("-fcaller-saves")
    #pragma GCC optimize("-fcrossjumping")
    #pragma GCC optimize("-fthread-jumps")
    #pragma GCC optimize("-funroll-loops")
    #pragma GCC optimize("-fwhole-program")
    #pragma GCC optimize("-freorder-blocks")
    #pragma GCC optimize("-fschedule-insns")
    #pragma GCC optimize("inline-functions")
    #pragma GCC optimize("-ftree-tail-merge")
    #pragma GCC optimize("-fschedule-insns2")
    #pragma GCC optimize("-fstrict-aliasing")
    #pragma GCC optimize("-fstrict-overflow")
    #pragma GCC optimize("-falign-functions")
    #pragma GCC optimize("-fcse-skip-blocks")
    #pragma GCC optimize("-fcse-follow-jumps")
    #pragma GCC optimize("-fsched-interblock")
    #pragma GCC optimize("-fpartial-inlining")
    #pragma GCC optimize("no-stack-protector")
    #pragma GCC optimize("-freorder-functions")
    #pragma GCC optimize("-findirect-inlining")
    #pragma GCC optimize("-fhoist-adjacent-loads")
    #pragma GCC optimize("-frerun-cse-after-loop")
    #pragma GCC optimize("inline-small-functions")
    #pragma GCC optimize("-finline-small-functions")
    #pragma GCC optimize("-ftree-switch-conversion")
    #pragma GCC optimize("-foptimize-sibling-calls")
    #pragma GCC optimize("-fexpensive-optimizations")
    #pragma GCC optimize("-funsafe-loop-optimizations")
    #pragma GCC optimize("inline-functions-called-once")
    #pragma GCC optimize("-fdelete-null-pointer-checks")
    #include<bits/stdc++.h>
    #define FOR(i,a,b) for(register int i=(a);i<=(b);++i)
    using namespace std;
    const int N = 50001;
    inline int read(){
    	int x=0,pos=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
    	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    	return pos?x:-x; 
    }
    #define db double 
    struct point{
    	db x,y;db dis;
    	point(db x=0,db y=0):x(x),y(y){dis=sqrt((x)*(x)+(y)*(y));}
    	//db gd(const point &b){
    	//	return sqrt((x-b.x)*(x-b.x)+(y-b.y)*(y-b.y));
    //	}
    	point operator -(point b){
    		return point(x-b.x,y-b.y);
    	}
    	point operator +(point b){
    		return point(x+b.x,y+b.y);
    	}
    	point operator *(db b){
    		return point(x*b,y*b);
    	}
    };
    point p[N];
    int n,m;
    db tot[N];
    db di=0;
    struct typ{
    	point s,t;int id;db dis;
    	typ(point s=point(0,0),point t=point(0,0),int id=0,db dis=0):s(s),t(t),id(id),dis(dis){}
    }; 
    typ v[N*2];
    db mn[N*2];
    int cmp(const typ &a,const typ &b){
    	if(a.id==b.id){
    		return a.dis<b.dis; 
    	}else return a.id<b.id;
    }
    db calc(typ a,typ b,db len){
    	point si=a.s+(b.s-a.s)*(len/(b.s-a.s).dis);
    	point ti=a.t+(b.t-a.t)*(len/(b.t-a.t).dis);
    	return (ti-si).dis;
    }
    #define pdi pair<db,int>
    #define fi first
    #define mp make_pair
    #define se second
    pdi vec[N*4];
    int tp=0,top=0,re=0;
    void add(db l,db r){
    	//printf("%f %f
    ",l,r);
    	int ss=((int)(l/di)),tt=((int)(r/di));
    	if(ss==tt){
    		l-=di*ss,r-=di*tt;
    		vec[++tp]=mp(l,1);
    		vec[++tp]=mp(r,-1);
    	}else{
    		re+=tt-ss-1;
    		//printf("%f %f
    ",l,r);
    		l-=di*ss,r-=di*tt;
    		//ori++;
    		vec[++tp]=mp(0,1);
    		vec[++tp]=mp(r,-1);
    		vec[++tp]=mp(l,1);
    		vec[++tp]=mp(di,-1);
    		//vec[++tp]=mp(di,-1);
    		//ed++;
    	}
    }
    db lmi[N*2],lmx[N*2],rmi[N*2],rmx[N*2]; 
    db lni[N*2],rni[N*2],cnc[N*2];
    void getmn(typ a,typ b,int id){
    	if((a.s-b.s).dis<1e-6) return;
    	db len=(a.s-b.s).dis;
    	db l=0,r=len;
    	while(r-l>1e-6){
    		db m1=l+(r-l)/3,m2=r-(r-l)/3;
    		if(calc(a,b,m1)<calc(a,b,m2)){
    			r=m2;
    		}else l=m1;
    	}
    	mn[id]=l;
    	lmi[id]=0,lmx[id]=l;
    	rmi[id]=l,rmx[id]=len;
    	cnc[id]=calc(a,b,l);
    }
    inline void update1(db lim){
    	for(register int i=2;i<=top;++i){
    		if(cnc[i]>lim) continue;
    		lmi[i]=lni[i],rmx[i]=rni[i];
    	}
    	if(cnc[1]>lim) return;
    		lmi[1]=lni[1],rmx[1]=rni[1];
    }
    inline void update2(db lim){
    	for(register int i=2;i<=top;++i){
    		if(cnc[i]>lim) continue;
    		lmx[i]=lni[i],rmi[i]=rni[i];
    	}
    	if(cnc[1]>lim) return;
    		lmx[1]=lni[1],rmi[1]=rni[1];
    }
    void solve(typ a,typ b,db lim,int id){
    //	printf("%f %f
    ",(a.s-b.s).dis,(a.t-b.t).dis);
    	//assert(fabs((a.s-b.s).dis-(a.t-b.t).dis)<1e-6);
    	db low=mn[id];
    	//db len=(a.s-b.s).dis;
    	if(calc(a,b,low)>lim) return;
    	db l=lmi[id],r=lmx[id];
    		while(r-l>1e-6){
    			db mid=(l+r)/2.0;
    			if(calc(a,b,mid)>lim) l=mid;
    			else r=mid;
    		}
    		//add(tot[a.id]+a.dis+l,tot[a.id]+a.dis+low);
    		lni[id]=l;
    	db ln=l; 
    		l=rmi[id],r=rmx[id];
    		while(r-l>1e-6){
    			db mid=(l+r)/2.0;
    			if(calc(a,b,mid)>lim) r=mid;
    			else l=mid;
    		}
    		add(tot[a.id]+a.dis+ln,tot[a.id]+a.dis+r);
    		rni[id]=r;
    }
    int cmp1(pdi a,pdi b){
    	if(fabs(a.fi-b.fi)>1e-6) return a.fi<b.fi;
    	else return a.se<b.se;
    }
    int check(db mid){
    	tp=0;re=0;
    	for(register int i=2;i<=top;++i){
    		solve(v[i-1],v[i],mid,i);
    	}
    	solve(v[top],v[1],mid,1); 
    	int res=re;
    	sort(vec+1,vec+tp+1,cmp1);
    	for(int i=1;i<=tp;++i){
    		res+=vec[i].se;if(res==m) return 1;
    		//printf("%d
    ",res);
    	}
    	return 0;
    }
    int main(){
    	freopen("n.in","r",stdin);
    	freopen("n.out","w",stdout);
    	n=read();m=read();
    	FOR(i,1,n){
    		int x=read(),y=read();
    		p[i]=point(x,y);
    		//p[i].x=read(),p[i].y=read();
    	} 
    	FOR(i,1,n){
    		tot[i]=di;
    		di+=(p[i%n+1]-p[i]).dis;
    	}
    	db w=0;int pos=1;
    	db dn=di;di=di/m;
    	if(m>n){
    		printf("%.10f",di);return 0;
    	}
    	FOR(i,1,n){
    		while(w+(p[pos%n+1]-p[pos]).dis<di) w+=(p[pos%n+1]-p[pos]).dis,pos=pos%n+1;
    		point nw=p[pos]+(p[pos%n+1]-p[pos])*((di-w)/((p[pos%n+1]-p[pos]).dis));
    		v[++top]=typ(p[i],nw,i,0); 
    		w-=(p[i%n+1]-p[i]).dis;
    	}
    	w=dn,pos=1;
    	FOR(i,1,n){
    		while(w-(p[pos%n+1]-p[pos]).dis>di) w-=(p[pos%n+1]-p[pos]).dis,pos=pos%n+1;
    		point nw=p[pos]+(p[pos%n+1]-p[pos])*((w-di)/((p[pos%n+1]-p[pos]).dis));
    		v[++top]=typ(nw,p[i],pos,w-di);
    		w+=(p[i%n+1]-p[i]).dis;
    	}
    	//cout<<clock()<<endl;
    	sort(v+1,v+top+1,cmp);
    	for(register int i=2;i<=top;++i){
    		getmn(v[i-1],v[i],i);
    	}
    	getmn(v[top],v[1],1); 
    	//cout<<clock()<<endl;
    	db l=0,r=1e7;
    	while(fabs(r-l)>1e-6){
    		db mid=(l+r)/2;
    		if(check(mid)) r=mid,update1(mid);
    		else l=mid,update2(mid);
    		//cout<<clock()<<endl;
    	}
    	printf("%.10f",r);
    	return 0;
    }
    
  • 相关阅读:
    java去除string类型里面的中括号
    java深拷贝浅拷贝
    前端接受数据去除[" "]的方法
    sql 查询近6 /xx个月/天 统计数据
    vue 定时器(定时任务)
    vue 二维码判断手机登录是哪个操作系统
    Connection is read-only. Queries leading to data modification are not allowed
    redis一闪而退解决办法
    前端的模糊查找
    vue笔记生命周期里面的某些函数
  • 原文地址:https://www.cnblogs.com/lcyfrog/p/13151754.html
Copyright © 2011-2022 走看看