zoukankan      html  css  js  c++  java
  • HDU3488 Tour KM

    原文链接http://www.cnblogs.com/zhouzhendong/p/8284304.html


    题目传送门 - HDU3488


    题意概括

      给一个n的点m条边的有向图。

      然后让你把这个图分成许多环,问环中边权和最小为多少。

      题目保证一定存在合法的方案。


    题解

      我们把每一个点扯成两个点。

      一个专门接受入度,一个专门接受出度,然后就是KM裸题了。

      数组模拟链表可能会比邻接矩阵快一些。


    代码

    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    #include <cstdio>
    using namespace std;
    const int INF=1e9+7;
    const int N=205,M=30005;
    struct Gragh{
    	int cnt,y[M],z[M],nxt[M],fst[N];
    	void clear(){
    		cnt=0;
    		memset(fst,0,sizeof fst);
    	}
    	void add(int a,int b,int c){
    		y[++cnt]=b,z[cnt]=c,nxt[cnt]=fst[a],fst[a]=cnt;
    	}
    }g;
    int T,n,m,match[N],ex[N],ey[N],minadd[N];
    bool visx[N],visy[N];
    bool Match(int x){
    	visx[x]=1;
    	for (int i=g.fst[x];i;i=g.nxt[i]){
    		int y=g.y[i];
    		if (visy[y])
    			continue;
    		int add=ex[x]+ey[y]-g.z[i];
    		if (!add){
    			visy[y]=1;
    			if (!match[y]||Match(match[y])){
    				match[y]=x;
    				return 1;
    			}
    		}
    		else
    			minadd[y]=min(minadd[y],add);
    	}
    	return 0;
    }
    int KM(){
    	memset(match,0,sizeof match);
    	memset(ey,0,sizeof ey);
    	for (int i=1;i<=n;i++){
    		ex[i]=-INF;
    		for (int j=g.fst[i];j;j=g.nxt[j])
    			ex[i]=max(ex[i],g.z[j]);
    	}
    	for (int i=1;i<=n;i++){
    		for (int j=1;j<=n;j++)
    			minadd[j]=INF;
    		while (1){
    			memset(visx,0,sizeof visx);
    			memset(visy,0,sizeof visy);
    			if (Match(i))
    				break;
    			int d=INF;
    			for (int j=1;j<=n;j++)
    				if (!visy[j])
    					d=min(d,minadd[j]);
    			for (int j=1;j<=n;j++){
    				if (visx[j])
    					ex[j]-=d;
    				if (visy[j])
    					ey[j]+=d;
    				else
    					minadd[j]-=d;
    			}
    		}
    	}
    	int ans=0;
    	for (int i=1;i<=n;i++){
    		int Max=-INF;
    		for (int j=g.fst[match[i]];j;j=g.nxt[j])
    			if (g.y[j]==i)
    				Max=max(Max,g.z[j]);
    		ans+=Max;
    	}
    	return ans;
    }
    int main(){
    	scanf("%d",&T);
    	while (T--){
    		scanf("%d%d",&n,&m);
    		g.clear();
    		for (int i=1,a,b,c;i<=m;i++){
    			scanf("%d%d%d",&a,&b,&c);
    			g.add(a,b,-c);
    		}
    		printf("%d
    ",-KM());
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    nginx 平滑升级和location配置案例
    nginx
    基于zabbix的监控keepalive脑裂
    KVM部署
    基于keepalived的lvs负载均衡http集群
    高可用keepalived
    KVM
    无向图中 生成树,完全图,连通图 的区别
    java中 is
    第一章——软件工程学概述 思维导图
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/HDU3488.html
Copyright © 2011-2022 走看看