zoukankan      html  css  js  c++  java
  • 最小树形图

    最小树形图学习笔记

    直接上代码吧

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=109;
    const int oo=1000000000;
    
    int n,m,r;
    int w[maxn][maxn];
    
    int flag[maxn];
    int pre[maxn],vis[maxn];
    
    int Mst(){
    	int ans=0;
    	
    	for(;;){
    		for(int i=1;i<=n;++i){
    			if(i==r||flag[i])continue;
    			w[i][i]=oo;pre[i]=i;
    			for(int j=1;j<=n;++j){
    				if(flag[j])continue;
    				if(w[j][i]<w[pre[i]][i])pre[i]=j;
    			}
    			if(pre[i]==i)return -1;
    		}
    		
    		int beg=0;
    		for(beg=1;beg<=n;++beg){
    			if(beg==r||flag[beg])continue;//!!!!!!
    			int x=beg,cnt=0;
    			while(x!=r&&pre[x]!=beg&&cnt<=n){
    				x=pre[x];++cnt;
    			}
    			if(x==r||cnt>n)continue;
    			break;
    		}
    		if(beg>n){
    			for(int i=1;i<=n;++i){
    				if(i!=r&&!flag[i]){
    					ans+=w[pre[i]][i];
    				}
    			}
    			return ans;
    		}
    		
    		int x=beg;
    		memset(vis,0,sizeof(vis));
    		for(;;){
    			ans+=w[pre[x]][x];x=pre[x];vis[x]=flag[x]=1;
    			if(x==beg)break;
    		}
    		flag[beg]=0;
    		
    		for(int i=1;i<=n;++i){
    			if(!vis[i])continue;
    			for(int j=1;j<=n;++j){
    				if(vis[j])continue;
    				if(w[i][j]<w[beg][j])w[beg][j]=w[i][j];
    				if(w[j][i]!=oo&&w[j][i]-w[pre[i]][i]<w[j][beg]){
    					w[j][beg]=w[j][i]-w[pre[i]][i];
    				}
    			}
    		}
    	}
    	return ans;
    }
    int main(){
    	scanf("%d%d%d",&n,&m,&r);
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=n;++j){
    			w[i][j]=oo;
    		}
    	}
    	while(m--){
    		int x,y,z;
    		scanf("%d%d%d",&x,&y,&z);
    		if(x!=y){
    			w[x][y]=min(w[x][y],z);
    		}
    	}
    	printf("%d
    ",Mst());
    	
    	return 0;
    }
    

    BZOJ 4349 最小树形图

    题解:显然是所有的堡垒先都打完一遍,

    然后还有需要打的堡垒就用入边权值最小的代价打

    求打完一遍的权值和

    建立虚点root,向1-n连边

    然后再连好读入的边,跑最小树形图就可以了

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn=109;
    const int oo=1000000000;
    
    int n,m,root;
    double ans=0;
    double A[maxn];int B[maxn];
    double w[maxn][maxn];
    
    double minedge[maxn];
    
    int flag[maxn];
    int vis[maxn],pre[maxn];
    
    double Mst(){
    	double ret=0;
    	
    	for(;;){
    		for(int i=1;i<=n;++i){
    			if(i==root||flag[i])continue;
    			w[i][i]=oo;pre[i]=i;
    			for(int j=1;j<=n;++j){
    				if(flag[j])continue;
    				if(w[j][i]<w[pre[i]][i])pre[i]=j;
    			}
    		}
    		
    		int beg;
    		for(beg=1;beg<=n;++beg){
    			if(beg==root||flag[beg])continue;
    			int x=beg,cnt=0;
    			while(x!=root&&pre[x]!=beg&&cnt<=n){
    				x=pre[x];++cnt;
    			}
    			if(x==root||cnt>n)continue;
    			break;
    		}
    		
    		if(beg>n){
    			for(int i=1;i<=n;++i){
    				if(!flag[i]&&i!=root){
    					ret+=w[pre[i]][i];
    				}
    			}
    			return ret;
    		}
    		
    		int x=beg;
    		memset(vis,0,sizeof(vis));
    		for(;;){
    			ret+=w[pre[x]][x];x=pre[x];vis[x]=flag[x]=1;
    			if(x==beg)break;
    		}
    		flag[x]=0;
    		
    		for(int i=1;i<=n;++i){
    			if(!vis[i])continue;
    			for(int j=1;j<=n;++j){
    				if(vis[j])continue;
    				if(w[i][j]<w[x][j])w[x][j]=w[i][j];
    				if(w[j][i]!=oo&&w[j][i]-w[pre[i]][i]<w[j][x])w[j][x]=w[j][i]-w[pre[i]][i];
    			}
    		}
    	}
    }
    
    int main(){
    //	freopen("fuck.in","r",stdin);
    	
    	scanf("%d",&n);
    	root=n+1;
    	for(int i=1;i<=n+1;++i){
    		for(int j=1;j<=n+1;++j){
    			w[i][j]=oo;
    		}
    	}
    	for(int i=1;i<=n;++i){
    		cin>>A[i]>>B[i];
    		w[root][i]=A[i];
    		minedge[i]=A[i];
    	}
    	
    	scanf("%d",&m);
    	while(m--){
    		int x,y;double z;
    		cin>>x>>y>>z;
    		if(x!=y){
    			w[x][y]=min(w[x][y],z);
    		}
    		minedge[y]=min(minedge[y],z);
    	}
    	n=n+1;
    	ans+=Mst();
    	for(int i=1;i<=n;++i)ans+=(B[i]-1)*minedge[i];
    	printf("%.2f
    ",ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    【计算机视觉】OpenCV篇(2)
    【计算机视觉】OpenCV篇(1)
    傅立叶分析与小波分析整理
    极简Python DeBug工具——PySnooper
    透过SourceTree再谈Git
    佳文赏析:How to uninstall Linux
    AI佳作解读系列(四)——数据增强篇
    AI佳作解读系列(三)——深度学习中的合成数据研究
    java基础 序列化反序列化流 实现Serializable 接口 自动装载序列号到对象文本文件如修改不能反序列化对象文本,除非自定义long型常量 打印流
    java基础IO流 复制键盘录入的目录,复制其中的.java文件到指定目录,指定目录中有重名,则改名 对加密文件计算字母个数
  • 原文地址:https://www.cnblogs.com/zzyer/p/9283173.html
Copyright © 2011-2022 走看看