zoukankan      html  css  js  c++  java
  • BZOJ 2285 [Sdoi2011]保密

    题解:

    求比值用分数规划,单个求太慢了套整体二分

    然后求二分图最小割

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<cmath>
    using namespace std;
    const double eps=1e-10;
    const int maxn=1000;
    const int oo=1000000000;
    
    int n,m;
    int n1,m1;
    double val[maxn];
    
    int dcmp(double x){
    	if(fabs(x)<eps)return 0;
    	if(x<0)return -1;
    	else return 1;
    }
    
    struct ShortestPath{
    	int rx[100009],ry[100009],s[100009],t[100009];
    	int cntedge;
    	int head[maxn];
    	int to[100009],nex[100009];
    	double dist[100009];
    	void Addedge(int x,int y,double z){
    		nex[++cntedge]=head[x];
    		to[cntedge]=y;
    		dist[cntedge]=z;
    		head[x]=cntedge;
    	}
    	
    	void readin(){
    		for(int i=1;i<=m;++i)scanf("%d%d%d%d",&rx[i],&ry[i],&t[i],&s[i]);
    	}
    	
    	queue<int>q;
    	int inq[maxn];
    	double d[maxn];
    	void Spfa(){
    		for(int i=1;i<=n;++i){
    			d[i]=oo;inq[i]=0;
    		}
    		inq[n]=1;d[n]=0;q.push(n);
    		while(!q.empty()){
    			int x=q.front();q.pop();inq[x]=0;
    			for(int i=head[x];i;i=nex[i]){
    				if(d[x]+dist[i]<d[to[i]]){
    					d[to[i]]=d[x]+dist[i];
    					if(!inq[to[i]]){
    						q.push(to[i]);
    						inq[to[i]]=1;
    					}
    				}
    			}
    		}
    	}
    	
    	int a[maxn],b[maxn],c[maxn];
    	void Div(int l,int r,double Lo,double Hi){
    		if(l>r)return;
    		if(dcmp(Lo-Hi)==0){
    			for(int i=l;i<=r;++i)val[a[i]]=Lo;
    			return;
    		}
    		double midans=(Lo+Hi)/2.0;
    		memset(head,0,sizeof(head));
    		cntedge=0;
    		for(int i=1;i<=m;++i)Addedge(rx[i],ry[i],t[i]-midans*s[i]);
    		Spfa();
    		int t1=0,t2=0;
    		for(int i=l;i<=r;++i){
    			if(d[a[i]]<=0){
    				b[++t1]=a[i];
    			}else{
    				c[++t2]=a[i];
    			}
    		}
    		for(int i=1;i<=t1;++i)a[l+i-1]=b[i];
    		for(int i=1;i<=t2;++i)a[l+t1+i-1]=c[i];
    		Div(l,l+t1-1,Lo,midans);
    		Div(l+t1,r,midans,Hi);
    	}
    	void Getst(){
    		for(int i=1;i<=n1;++i)a[i]=i;
    		for(int i=1;i<=n1;++i)val[i]=oo;
    		Div(1,n1,0,1000.0);
    	}
    }P;
    
    
    struct NetworkFlow{
    	struct Edge{
    		int from,to;
    		double cap,flow;
    	};
    	vector<int>G[maxn];
    	vector<Edge>edges;
    	void Addedge(int x,int y,double z){
    		Edge e;
    		e.from=x;e.to=y;e.cap=z;e.flow=0;
    		edges.push_back(e);
    		e.from=y;e.to=x;e.cap=0;e.flow=0;
    		edges.push_back(e);
    		int c=edges.size();
    		G[x].push_back(c-2);
    		G[y].push_back(c-1);
    	}
    	
    	int s,t;
    	int d[maxn];
    	int vis[maxn];
    	queue<int>q;
    	int Bfs(){
    		memset(vis,0,sizeof(vis));
    		vis[s]=1;d[s]=0;q.push(s);
    		while(!q.empty()){
    			int x=q.front();q.pop();
    			for(int i=0;i<G[x].size();++i){
    				Edge e=edges[G[x][i]];
    				if((dcmp(e.cap-e.flow)>0)&&(!vis[e.to])){
    					vis[e.to]=1;
    					d[e.to]=d[x]+1;
    					q.push(e.to);
    				}
    			}
    		}
    		return vis[t];
    	}
    	
    	double Dfs(int x,double a){
    		if((x==t)||(dcmp(a)==0))return a;
    		
    		double nowflow=0,f=0;
    		for(int i=0;i<G[x].size();++i){
    			Edge e=edges[G[x][i]];
    			if(d[x]+1==d[e.to]){
    				f=Dfs(e.to,min(a,e.cap-e.flow));
    				if(dcmp(f)>0){
    					nowflow+=f;
    					a-=f;
    					edges[G[x][i]].flow+=f;
    					edges[G[x][i]^1].flow-=f;
    					if(dcmp(a)==0)break;
    				}
    			}
    		}
    		return nowflow;
    	}
    	
    	double Maxflow(){
    		double flow=0;
    		while(Bfs())flow+=Dfs(s,oo*1.0);
    		return flow;
    	}
    	
    	void Sol(){
    		s=n1+1;t=s+1;
    		for(int i=1;i<=n1;++i){
    			if(i%2)Addedge(s,i,val[i]);
    			else Addedge(i,t,val[i]);
    		}
    		while(m1--){
    			int x,y;
    			scanf("%d%d",&x,&y);
    			if((dcmp(val[x]-1000)==0)&&(dcmp(val[y]-1000)==0)){
    				printf("-1
    ");return;
    			}
    			Addedge(x,y,oo*1.0);
    		}
    		printf("%.1f
    ",Maxflow());
    	}
    }F;
    
    int main(){
    	scanf("%d%d",&n,&m);
    	P.readin();
    	scanf("%d%d",&m1,&n1);
    	P.Getst();
    	F.Sol();
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    非递归实现二叉树先序、中序和后序遍历
    领益科技:Windows Server 2012 R2 强制卸载域控制器
    Zabbix调优不完全指南(https://www.jianshu.com/p/2d911d55448f)
    Linux下基础查看命令
    Linux下的快捷键
    给Linux系统新增加一块硬盘
    领益智造:Windows中的备份和还原
    领益智造:AD中修改OU下面用户的属性
    领益科技:AD中批量创建域用户(创建Mac地址账号)
    Linux常见企业面试题
  • 原文地址:https://www.cnblogs.com/zzyer/p/8546386.html
Copyright © 2011-2022 走看看