• CF1264E Beautiful League 解题报告


    给出一个 (n) 个点的竞赛图,有 (m) 条边已经确定方向,求出最多可能的三元环个数。

    (nle 50 , mle frac{n(n-1)}{2})

    没有想到的网络流题,我还是太菜了qaq

    三个点构不成三元环的充分必要条件是存在一个点仅对于这三个点的出度为 (2)

    假设第 (i) 个点的出度为 (d_i) ,通过容斥,三元环的个数为 (frac{n(n-1)(n-2)}{6} - sumlimits_{i=1}^n inom{d_i}{2})

    那么目标就转化为最小化 (sumlimits_{i=1}^n inom{d_i}{2}) ,考虑使用网络流,非固定的边可以新建一个点,源点向新点连一条流量为 (1) 的边,新点再向两端的点各连一条流量为 (1) 的边,这样流到第 (i) 个点的流量就是 (d_i) ,而 (inom{d_i}{2}) 可以通过差分展开成 (sumlimits_{j=1}^{d_i} (j-1)) ,那么可以对于每个点,向汇点连 (n) 条边,第 (j) 条边的流量为 (1) ,费用为 (j-1) ,跑一遍最小费用最大流就可以统计最终答案了。

    其实挺套路,果然是自己菜(

    不知道为什么我跑了一遍最大费用也过了

    #include<bits/stdc++.h>
    using namespace std;
    
    const int M=1e5+5,N=105,inf=1e9;
    
    int n,m,num,S,T,Map[N][N];
    int read(){
    	int x=0,y=1;char ch=getchar();
    	while(ch<'0'||ch>'9') y=(ch=='-')?-1:1,ch=getchar();
    	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    	return x*y;
    }
    
    int tot=1,first[M];
    struct Edge{ int nxt,to,w,c; }e[M<<1];
    void add(int x,int y,int w,int c){
    	e[++tot]=(Edge){first[x],y,w,c};
    	first[x]=tot;
    }
    void addedge(int x,int y,int w,int c){ add(x,y,w,c),add(y,x,0,-c); }
    
    queue<int> Q;
    int dis[M],pre[M],minn[M];bool vis[M];
    bool spfa(){
    	while(!Q.empty()) Q.pop();
    	for(int i=0;i<=num;i++) dis[i]=inf,vis[i]=0;
    	Q.push(S),dis[S]=0,minn[S]=inf,vis[S]=1;
    	while(!Q.empty()){
    		int u=Q.front();Q.pop();vis[u]=0;
    		for(int i=first[u];i;i=e[i].nxt){
    			int v=e[i].to,w=e[i].w,c=e[i].c;
    			if(w&&dis[v]>dis[u]+c){
    				pre[v]=i;dis[v]=dis[u]+c;
    				minn[v]=min(minn[u],w);
    				if(!vis[v]) vis[v]=1,Q.push(v);
    			}
    		}
    	}
    	return dis[T]<inf;
    }
    void EK(){
    	while(spfa()){
    		int u=T;
    		while(u!=S){
    			int i=pre[u];
    			e[i].w-=minn[T],e[i^1].w+=minn[T];
    			u=e[i^1].to;
    		}
    	}
    }
    
    void solve(){
    	n=read(),m=read();S=0,T=1,num=n+1;
    	for(int i=1;i<=m;i++){
    		int x=read(),y=read();
    		Map[x][y]=1,Map[y][x]=-1;
    		addedge(S,x+1,1,0);
    	}
    	for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if(Map[i][j]==0)
    		Map[i][j]=Map[j][i]=++num,addedge(S,num,1,0),addedge(num,i+1,1,0),addedge(num,j+1,1,0);
    	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) addedge(i+1,T,1,j-1);
    	EK();
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++){
    			if(i==j) printf("0");
    			else{
    				int x=Map[i][j],flag=0;
    				if(x==1) printf("1");
    				else if(x==-1) printf("0");
    				else{
    					for(int k=first[x];k;k=e[k].nxt){
    						int v=e[k].to;
    						if(v==i+1&&!e[k].w) flag=1;
    					}
    					printf("%d",flag);
    				}
    			}
    		}
    		printf("
    ");
    	}
    }
    
    signed main(){
    	solve();
    }
    
  • 相关阅读:
    INFORMATION_SCHEMA.INNODB_LOCKS
    INFORMATION_SCHEMA.INNODB_TRX 详解
    zabbix 通过key 获取
    匿名hash
    [] 和{} 匿名引用
    perl 初始化Hash
    9.2 数组的散列
    数组的数组
    RMAN恢复目录
    验证备份前设置CONFIGURE CONTROLFILE AUTOBACKUP ON/OFF; 的区别
  • 原文地址:https://www.cnblogs.com/wzp-blog/p/14359460.html
Copyright © 2020-2023  润新知