• 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();
    }
    
  • 相关阅读:
    谷歌火狐浏览器限制的端口
    Web Api 内部数据思考 和 利用http缓存优化 Api
    Web Api 端点设计 与 Oauth
    FI-FBV0
    Others-SAP hybris 介绍
    ABAP-表修改日志存储
    TR-银行通信相关文档
    ABAP-Eclipse ADT中创建ABAP CDS视图
    TR-业务流程图
    FPM-OVP增强实例-银行账户
  • 原文地址:https://www.cnblogs.com/wzp-blog/p/14359460.html
Copyright © 2020-2023  润新知