zoukankan      html  css  js  c++  java
  • [WC2007]剪刀石头布


    题解

    给出一个竞赛图的一些边,你需要定向剩下的边,使得形成的三元环最少
    (i)如果能赢(j)就连一条(i o j)的边
    可以发现直接统计三元环的总个数是十分困难的
    我们可以考虑反面计数
    (n)个点的竞赛图的三元环的最大个数为(C_{n}^{3})
    我们只需要考虑去掉每三个点不能形成三元环的条件就行了
    有三条边形不成三元环的条件就是一个点的入度/出度(>1)
    所以如果一个点的入度为(k)
    那么ta的影响就是(C_{k}^{3})
    然后差分一下(C_{k}^{3}-C_{k-1}^{3}=k-1)
    也就是说入度每增加(1)
    那么答案就会增加当前的入度
    这样我们就可以跑费用流了
    从源点连向每条边,流量为1,费用为0
    从每条边连向两个端点,流量为1,费用为0
    从每个点连(n-1)条边到(T),流量为(0sim n-2)
    最小费用最大流即可

    代码

    // d[u] 表示入度 
    // 如果i赢了j,那么++d[j] 
    // 流谁谁输 
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int M = 105 ;
    const int N = 5205 ;
    const int INF = 1e9 ;
    using namespace std ;
    
    inline int read() {
    	char c = getchar() ; int x = 0 , w = 1 ;
    	while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
    	while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
    	return x*w ;
    }
    
    bool exist[N] ;
    int n , cnt , S , T ;
    int C[M][M] , ans , num = 1 , hea[N] ;
    int d[M] , sit[M][M] , id[M][M] ;
    int dis[N] , pre[N] ;
    
    struct E {
    	int nxt , to , dis , cst ;
    } edge[N * 50] ;
    inline void Insert_edge(int from , int to , int dis , int cst) {
    	edge[++num].nxt = hea[from] ; edge[num].to = to ;
    	edge[num].dis = dis ; edge[num].cst = cst ; hea[from] = num ;
    }
    inline void add_edge(int u , int v , int w , int c) {
    	Insert_edge(u , v , w , c) ;
    	Insert_edge(v , u , 0 , -c) ;
    }
    inline bool spfa() {
    	queue < int > q ; q.push(S) ; pre[T] = -1 ;
    	memset(dis , 31 , sizeof(dis)) ; dis[S] = 0 ; 
    	while(!q.empty()) {
    		int u = q.front() ; q.pop() ; exist[u] = false ;
    		for(int i = hea[u] ; i ; i = edge[i].nxt) {
    			int v = edge[i].to ; 
    			if(dis[v] > dis[u] + edge[i].cst && edge[i].dis > 0) {
    				dis[v] = dis[u] + edge[i].cst ; pre[v] = i ;
    				if(!exist[v]) { exist[v] = true ; q.push(v) ; }
    			}
    		}
    	}
    	return (pre[T] > 0) ;
    }
    inline void mcmf() {
    	while(spfa()) {
    		int diss = INF ;
    		for(int i = T ; i != S ; i = edge[pre[i] ^ 1].to) diss = min(diss , edge[pre[i]].dis) ;
    		for(int i = T ; i != S ; i = edge[pre[i] ^ 1].to) edge[pre[i]].dis -= diss , edge[pre[i] ^ 1].dis += diss ;
    		ans -= dis[T] * diss ;
    	}
    }
    int main() {
    	n = read() ; S = 0 ;
    	for(int i = 0 ; i <= n ; i ++) {
    		C[i][0] = 1 ;
    		for(int j = 1 ; j <= i ; j ++)
    			C[i][j] = C[i - 1][j] + C[i - 1][j - 1] ;
    	}	
    	ans = C[n][3] ;
    	for(int i = 1 ; i <= n ; i ++)
    		for(int j = 1 ; j <= n ; j ++)
    			sit[i][j] = read() ;
    	cnt = n ;
    	for(int i = 1 ; i <= n ; i ++)
    		for(int j = i + 1 ; j <= n ; j ++) {
    			if(sit[i][j] == 1) {
    				++ d[j] ;
    				ans -= d[j] - 1 ;
    			}
    			else if(sit[i][j] == 0) {
    				++ d[i] ;
    				ans -= d[i] - 1 ;
    			}
    			else {
    				++ cnt ;
    				id[i][j] = id[j][i] = cnt ;
    				add_edge(S , cnt , 1 , 0) ;
    				add_edge(cnt , i , 1 , 0) ;
    				add_edge(cnt , j , 1 , 0) ;
    			}
    		}
    	T = ++ cnt ;
    	for(int i = 1 ; i <= n ; i ++)
    		for(int j = d[i] + 1 ; j < n ; j ++)
    			add_edge(i , T , 1 , j - 1) ;		
    	mcmf() ;
    	printf("%d
    ",ans) ;
    	for(int i = 1 ; i <= n ; i ++)
    		for(int j = i + 1 , _loser ; j <= n ; j ++)
    			if(sit[i][j] == 2) {
    				int u = id[i][j] ;
    				for(int k = hea[u] ; k ; k = edge[k].nxt) {
    					int v = edge[k].to ; 
    					if(v >= 1 && v <= n && edge[k].dis == 0) {
    						_loser = v ;
    						break ;
    					} 
    				}
    			    if(_loser == i) sit[i][j] = 0 , sit[j][i] = 1 ;
    			    else sit[i][j] = 1 , sit[j][i] = 0 ;
    			} 
    	for(int i = 1 ; i <= n ; i ++) {
    		for(int j = 1 ; j <= n ; j ++)
    			printf("%d ",sit[i][j]) ;
    		printf("
    ") ;
    	}
    	return 0 ;
    }
    
    
  • 相关阅读:
    冒泡排序
    Bootstrap fileinput v1.0(ssm版)
    Bootstrap table后端分页(ssm版)
    Bootstrap table前端分页(ssm版)
    北京鱼乐贝贝面试题
    通过前端控制器源码分析springmvc的执行过程
    java Pattern(正则)类
    ssm所需要的pom(jre8、tomcat8、spring4)
    Java 流(Stream)、文件(File)和IO
    idea构建一个简单的maven_web项目
  • 原文地址:https://www.cnblogs.com/beretty/p/10781579.html
Copyright © 2011-2022 走看看