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

    link

    $solution:$

    考虑如何求完全图上的三元环个数,考虑对于 $(i,j,k)$ ,若其不是三元环则必有一个的度数为 $2$ ,则总个数为 $$dbinom{n}{3}-sum_{i=1}^n dbinom{d_i}{2}$$ 

    若要求式子最小,则 $$min{sum_{i=1}^n dbinom{d_i}{2}}=min{sum_{i=1}^n d_i^2}$$ 

    那么问题便转化为了给每条边定向,使得每个点度数平方的和最小,对于二选一问题考虑网络流求解。维护平方差量,每次增加 $1^2-0^2,2^2-1^2,3^2-2^2,4^2-3^2$ 等,跑最小费用最大流即可。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<climits>
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    const int MAXN=50001;
    const int MAXM=301;
    queue<int> que;
    struct node{
        int u,v,w,cost,nex;
    }x[MAXN<<1];
    int head[MAXN],cnt,N,M,MM[MAXM][MAXM],S,T,INF=INT_MAX,Me[MAXN][MAXM];
    void add(int u,int v,int w,int cost){
        x[cnt].u=u,x[cnt].v=v,x[cnt].w=w,x[cnt].cost=cost,x[cnt].nex=head[u],head[u]=cnt++;swap(u,v),w=0,cost=-cost;
        x[cnt].u=u,x[cnt].v=v,x[cnt].w=w,x[cnt].cost=cost,x[cnt].nex=head[u],head[u]=cnt++;return;
    }
    pair<int,int> pa[MAXN];
    int num,dis[MAXN],vis[MAXN],MC;
    bool bfs(){
        memset(vis,0,sizeof(vis)),memset(dis,127/3,sizeof(dis));int inf=dis[0];dis[S]=0;
        vis[S]=1;que.push(S);
        while(!que.empty()){
            int xx=que.front();que.pop();vis[xx]=0;
            for(int i=head[xx];i!=-1;i=x[i].nex){
                if(dis[x[i].v]>dis[xx]+x[i].cost&&x[i].w){
                    dis[x[i].v]=dis[xx]+x[i].cost;
                    if(!vis[x[i].v]) vis[x[i].v]=1,que.push(x[i].v);
                }
            }
        }return dis[T]!=inf;
    }
    int dfs(int u,int flow){
        if(u==T) return flow;int used=0;vis[u]=1;
        for(int i=head[u];i!=-1;i=x[i].nex){
            if(!vis[x[i].v]&&x[i].w&&dis[x[i].v]==dis[u]+x[i].cost){
                int slow=dfs(x[i].v,min(flow-used,x[i].w));used+=slow;MC+=slow*x[i].cost;
                x[i].w-=slow,x[i^1].w+=slow;
                if(flow==used) break;
            }
        }if(!used) dis[u]=-1;
        return used;
    }
    int Dinic(){
        int Ans=0;
        while(bfs()){memset(vis,0,sizeof(vis));Ans+=dfs(S,INF);}
        return Ans;
    }
    int Ans[MAXM][MAXM];
    int GG[MAXM][MAXM],d[MAXN];
    int calc(int x){if(x<2) return 0;return (x*(x-1))/2;}
    int main(){
    //    freopen("7.in","r",stdin);
        memset(head,-1,sizeof(head));
        N=read();
        for(int i=1;i<=N;i++) for(int j=1;j<=N;j++){
            int e=read();
            if(e==1) MM[i][j]=1;
            if(e==0) MM[i][j]=2;
        }
        num=N;
        for(int i=1;i<=N;i++){
            for(int j=i+1;j<=N;j++){
                pa[++num].first=i,pa[++num].second=j;GG[i][j]=num;
                if(MM[i][j]==1){add(num,i,1,0);continue;}
                if(MM[i][j]==2){add(num,j,1,0);continue;}
                add(num,i,1,0),add(num,j,1,0);
            }
        }
        for(int i=N+1;i<=num;i++) add(S,i,1,0);T=++num;
        for(int i=1;i<=N;i++){
            for(int j=1;j<=N;j++) add(i,T,1,j*j-(j-1)*(j-1));
        }
        int G=Dinic();
        for(int i=0;i<cnt;i++) if(x[i].u>N&&x[i].v<=N) Me[x[i].u][x[i].v]=x[i].w;
        for(int i=1;i<=N;i++){
            for(int j=i+1;j<=N;j++){
                if(MM[i][j]==1){Ans[i][j]=1;continue;}
                if(MM[i][j]==2){Ans[i][j]=0;continue;}
                int las=GG[i][j];
    //            printf("%d %d %d
    ",las,i,j);
                if(Me[las][i]==1){Ans[i][j]=0;continue;}
                Ans[i][j]=1;continue;
            }
        }
        for(int i=1;i<=N;i++)
            for(int j=i+1;j<=N;j++) Ans[j][i]=Ans[i][j]^1;
        for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) if(Ans[i][j]) d[j]++;
        int res=(N*(N-1)*(N-2))/6;
        for(int i=1;i<=N;i++) res-=calc(d[i]);
        printf("%d
    ",res);
        for(int i=1;i<=N;i++){
            for(int j=1;j<=N;j++) printf("%d ",Ans[i][j]);
            printf("
    ");
        }return 0;
    }/*3
    0 1 2
    0 0 2
    2 2 0
    */
    View Code
  • 相关阅读:
    静态构造函数
    js-----Date对象
    JS中Math函数的常用方法
    js 简单数据类型和复杂数据类型的区别
    js new关键字 和 this详解
    JS 对象的三种创建方式
    js 预解析
    JS作用域问题
    js实现斐波那契数列
    JS 三元表达式
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/12056459.html
Copyright © 2011-2022 走看看