传送门

解题思路

  考虑全集-不能构成三元环的个数。如果三个点不能构成三元环,一定有一个点的入度为\(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. c++11 中的注意事项

    1. C++11标准中让类的析构函数默认也是noexcept(true)的. 但如果显式地为析构函数指定了noexcept,或者类的基类或成员有noexcept(false)的析构函数,析构函数就不会 ...

  2. UNP学习 Unix域协议

    Unix域协议并不是一个实际的协议族,它只是在同一台主机上进行客户-服务器通信时,使用与在不同主机上的客户和服务器间通信时相同的API的一种方法. 当客户和服务器在同一台主机上时,Unix域协议是这套 ...

  3. POJ 3126 Prime Path (bfs+欧拉线性素数筛)

    Description The ministers of the cabinet were quite upset by the message from the Chief of Security ...

  4. AcWing 241. 楼兰图腾 (树状数组)打卡

    题目:https://www.acwing.com/problem/content/description/243/ 题意:给你n个点,问你 V 和  ^的图腾有多少个 思路:比如V 其实就是找当前点 ...

  5. 一.jenkins安装(windows环境)

    前提:jdk等已安装 jenkins下载地址:https://jenkins.io/download/ 以我目前的知识记录两种启动方式: 1.直接下载war包 通过   java -jar jenki ...

  6. 测试过程中bug分类

    测试的核心任务是发现bug.在这之前是分析需求,之后是跟踪bug.跳出具体的项目来看,所有的bug无非是以下五大类. 软件没有实现应该实现的功能:如指定的登录功能. 软件出现了本应该避免的错误:如用户 ...

  7. Java短路运算符和非短路运算符

    在Java中短路运算符指的是"&&"(与) 和"||"(或) ,非短路运算符指的是"&" 和"|" ...

  8. Portal for ArcGIS启动失败,无法访问任何门户计算机,请联系您的系统管理员。

    1.如题,打开Portal门户的时候,发现: 2.检查日志发现Portal for ArcGIS没启动,日志地址:D:\Program Files\ArcGIS\Portal\framework\se ...

  9. Jeecg_Jflow整合记录

    系统组织机构 t_s_deparselect * from t_s_departselect * from t_s_depart where id='402888fd6a8c24e9016a8c531 ...

  10. kruskal算法【最小生成树2】

    设G=(V,E)是无向连通带权图,V={1,2,…,n}: 设最小生成树T=(V,TE),该树的初始状态为只有n个顶点而无边的非连通图T=(V,{}),Kruskal算法将这n个顶点看成是n个孤立的连 ...