传送门

解题思路

  考虑全集-不能构成三元环的个数。如果三个点不能构成三元环,一定有一个点的入度为\(2\),继续扩展,如果一个点的度数为\(3\),则会失去3个三元环。对于一个点来说,它所产生的不能构成三元环的贡献为\(C (deg[x],2)\),而度数每增加\(1\),对于答案的影响就是\(C(deg[x]+1,2)-C(deg[x],2)=deg[x]\),然后就可以建图了。考虑把边当做点,对于一条未确定的边来说,它只能对两个节点中的一个产生\(1\)个度数的贡献,所以让每个边向点连流量为1,费用为0的边。然后让源点向每条未确定的边连流量为1,费用为0的边。再让每个点向汇点连流量为\(1\),费用为\(deg[x],deg[x]+1,deg[x]+2,...n\)的边。跑一遍费用流。

代码


#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
 
using namespace std;
const int MAXN = 100005;
const int MAXM = 500005;
const int inf = 0x3f3f3f3f;
 
inline int rd(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    return f?x:-x;
}
 
int n,head[MAXN],cnt=1,to[MAXM<<1],nxt[MAXM<<1],val[MAXM<<1],cost[MAXM<<1];
int deg[MAXN],num,S,T,op[105][105],dis[MAXN],incf[MAXN],pre[MAXN],ans,tmp[105][105];
bool vis[MAXN];
queue<int> Q;
 
inline void add(int bg,int ed,int w,int z){
    to[++cnt]=ed,nxt[cnt]=head[bg],val[cnt]=w,cost[cnt]=z,head[bg]=cnt;
}
 
bool spfa(){
    while(Q.size()) Q.pop();
    memset(dis,0x3f,sizeof(dis));
    memset(vis,false,sizeof(vis));
    Q.push(S);vis[S]=1;incf[S]=inf;dis[S]=0;
    while(Q.size()){
        int x=Q.front();Q.pop();vis[x]=0;
        for(int i=head[x];i;i=nxt[i]){
            int u=to[i];
            if(dis[x]+cost[i]<dis[u] && val[i]){
                dis[u]=dis[x]+cost[i];
                incf[u]=min(incf[x],val[i]);
                pre[u]=i;
                if(!vis[u]) vis[u]=1,Q.push(u);
            }
        }
    }
    return (dis[T]==inf)?0:1;
}
 
inline void update(){
    int x=T,i;
    while(x!=S){
        i=pre[x];
        val[i]-=incf[T];
        val[i^1]+=incf[T];
        x=to[i^1];
    }
    ans-=incf[T]*dis[T];
}
 
int main(){
    n=rd();int x;T=n+2;S=n+1;num=T;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            x=rd();op[i][j]=x;
            if(x==1) deg[i]++;
        }
    for(int i=1;i<=n;i++) if(deg[i]>1) ans-=deg[i]*(deg[i]-1)/2;
    for(int i=1;i<=n;i++)
        for(int j=deg[i];j<=n;j++)
            add(i,T,1,j),add(T,i,0,-j);
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
            if(op[i][j]==2){
                num++;add(S,num,1,0);add(num,S,0,0);
                add(num,i,1,0),add(i,num,0,0);
                add(num,j,1,0),add(j,num,0,0);
                tmp[i][j]=tmp[j][i]=num;
            }
    while(spfa()) update();
    ans+=n*(n-1)*(n-2)/6;
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++) 
            if(op[i][j]==2){
                for(int k=head[tmp[i][j]];k;k=nxt[k]){
                    if(to[k]==S) continue;
                    if(!val[k]) {
                        if(to[k]==i) op[i][j]=1,op[j][i]=0;
                        else op[j][i]=1,op[i][j]=0;
                    }
                }
            }
    printf("%d\n",ans);
    for(int i=1;i<=n;i++){  
        for(int j=1;j<=n;j++)
            printf("%d ",op[i][j]);
        putchar('\n');
    }
    return 0;
}

BZOJ 2597: [Wc2007]剪刀石头布(费用流)的更多相关文章

  1. BZOJ.2597.[WC2007]剪刀石头布(费用流zkw)

    BZOJ 洛谷 \(Description\) 给定一张部分边方向已确定的竞赛图.你需要给剩下的边确定方向,使得图中的三元环数量最多. \(n\leq100\). \(Solution\) 这种选择之 ...

  2. bzoj 2597 [Wc2007]剪刀石头布——费用流

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2597 三个人之间的关系,除了“剪刀石头布”,就是有一个人赢了2局:所以考虑算补集,则每个人对 ...

  3. bzoj 2597: [Wc2007]剪刀石头布【最小费用最大流】

    脑子不太清楚一个zz问题调了好久-- 首先正难则反,因为三元环好像没什么特点,就考虑让非三元环个数最小 考虑非三元环特点,就是环上一定有一个点的入度为2,联系整张图,三元环个数就是每个点C(入度,2) ...

  4. [WC2007]剪刀石头布——费用流

    比较有思维含量的一道题 题意:给混合完全图定向(定向为竞赛图)使得有最多的三元环 三元环条件要求比较高,还不容易分开处理. 正难则反 考虑,什么情况下,三元组不是三元环 一定是一个点有2个入度,一个点 ...

  5. 2597: [Wc2007]剪刀石头布

    2597: [Wc2007]剪刀石头布 链接 分析: 费用流. 首先转化一下问题,整张图最优的情况是存在$C_n^3$个,即任意3个都行,然后考虑去掉最少不满足的三元环. 如果u赢了v,u向v连一条边 ...

  6. [bzoj 1449] 球队收益(费用流)

    [bzoj 1449] 球队收益(费用流) Description Input Output 一个整数表示联盟里所有球队收益之和的最小值. Sample Input 3 3 1 0 2 1 1 1 1 ...

  7. bzoj 1070: [SCOI2007]修车 费用流

    1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2785  Solved: 1110[Submit][Status] ...

  8. Luogu4249 WC2007 石头剪刀布 费用流

    传送门 考虑竞赛图三元环计数,设第\(i\)个点的入度为\(d_i\),根据容斥,答案为\(C_n^3 - \sum C_{d_i}^2\) 所以我们需要最小化\(\sum C_{d_i}^2\) 考 ...

  9. BZOJ 3171 循环格(费用流)

    题意 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位置(r,c),你可以沿着箭头防线在格子间行走.即如果(r ...

随机推荐

  1. 如何让EditText不能自动获取焦点(转)

    转载地址:http://blog.csdn.net/subaohao/article/details/9043895 在activity中放置了1个或1个以上的EditText,进入该activity ...

  2. 使用js在页面上新建文件夹

    使用js在页面上新建文件夹 <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...

  3. 树状数据删除(TP5)

    应用场景:类似上图中树状菜单,选中一级菜单 点击上方删除按钮 所有子菜单删除 以下是代码截图(代码基于 TP5)

  4. .net报错大全

    1.未能加载文件或程序集“Newtonsoft.Json, Version=4.5.0.0"[已解决] 解决方案:https://blog.csdn.net/mzl87/article/de ...

  5. camunda流程实例启动的一些简单操作

    public class ZccRuntimeService { RuntimeService runtimeService; RepositoryService repositoryService; ...

  6. PHP数组循环遍历的几种方式

    PHP数组循环遍历 1.for循环 <?php //语法 for (init counter; test counter; increment counter) { code to be exe ...

  7. QQ邮箱客户端配置

    接收协议:IMAP 接收邮箱服务器地址:imap.qq.com 端口:993 加密方法:TLS 发送协议:SMTP 发送服务器:smtp.qq.com 端口:465 加密方法:TLS

  8. 时间同步服务器NTP

    NTP服务器        NTP(Network Time Protocol)[网络时间协议],它是用来同步网络中各个计算机的时间的协议,它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒, ...

  9. python2和python3中int整型数据的不同之处

    python2中的除法,结果为整型数字(int型),例如 10/5=2,10/3=3,小数位向下取整 python3中的除法,结果为浮点型数字(float型)结果小数位最多保留16位小数

  10. linux 下安装chrome的rpm包

    1. 下载chrome的rpm包,假设叫cho. 2.执行命令 rpm -ivh cho 3.报错提示需要lsb>=4.0,执行命令 yum install lsb 等待安装完毕. 4. 重新执 ...