线切割加工报价单表格_最大费用最大流

线切割加工报价单表格_最大费用最大流[WC2007]剪刀石头布——费用流

大家好,又见面了,我是你们的朋友全栈君。

比较有思维含量的一道题

题意:给混合完全图定向(定向为竞赛图)使得有最多的三元环

三元环条件要求比较高,还不容易分开处理。

正难则反

考虑,什么情况下,三元组不是三元环

一定是一个点有2个入度,一个点有2个出度,另一个点一个入度,一个出度

也就是说,每存在一个>=2入度的点,那么会减少一些三元环

进而考虑,如果一个点有d个入度,那么减少的三元环其实是:C(d,2),即,包括它自己,再包括任意两个指向它的点(这里,a指向b,代表a能赢b),构成的三元组都不是三元环

考虑每个点作为某些个非法三元组的话,那么,

总共的三元环是:C(n,3)-∑C(du[i],2)

C(du[i],2)统计了所有与i有关的非法三元组,所以不重不漏统计完了。

 

怎样最小化这个∑?

定向,就是某些点的入度增加的过程。所以考虑某个点增加一个入度,减少的三元环的数量是多少。

即C(d+1,2)-C(d,2)=d即减少原来度数的三元环

这个减少是逐一增加的,n*(n-1)/2是下凸函数,可以考虑拆边费用流。

 

这个题的具体做法是:

把每个要定向的边看做一个点,从S到这个点连(1,0),意义是只能确定一个方向

这个点向所代表的边的两个原图端点连(1,0)的边,意义是增加入度,且只能给一个增加

每个原图 节点向T连(1,d),(1,d+1)…(1,d+n-2)的边,意义是,每增加一个入度,就会增加d的代价

最小费用最大流,spfa恰好先选择d,再选择d+1,,,,刚好符合实际的代价

最大流之后,每个边都定向完毕,而且增加的代价也都是对的。

 

至于输出方案,找每个边的代表点,看其哪一侧流量是0,就是哪一侧输。

 

代码:

#include<bits/stdc++.h>
#define il inline
#define reg register int
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
    char ch;bool fl=false;
    while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
namespace Miracle{
const int N=105;
const int inf=0x3f3f3f3f;
int n,s,m,t;
struct node{
    int nxt,to,w,v;
}e[2*(N*N+N*N*2+N*N)];
int hd[N+N*N],cnt=1;
void add(int x,int y,int w,int v){
    e[++cnt].nxt=hd[x];
    e[cnt].to=y;
    e[cnt].v=v;
    e[cnt].w=w;
    hd[x]=cnt;
    
    e[++cnt].nxt=hd[y];
    e[cnt].to=x;
    e[cnt].w=0;
    e[cnt].v=-v;
    hd[y]=cnt;
}
int mp[N][N];
int op[N][N];
queue<int>q;
bool vis[N+N*N];
int dis[N*N+N];
int incf[N*N+N],pre[N*N+N];
bool spfa(){
    while(!q.empty()) q.pop();
    memset(dis,inf,sizeof dis);
    dis[s]=0;
    q.push(s);
    pre[s]=0;
    incf[s]=inf;
    while(!q.empty()){
        int x=q.front();q.pop();
        vis[x]=0;
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(e[i].w){
                if(dis[y]>dis[x]+e[i].v){
                    dis[y]=dis[x]+e[i].v;
                    pre[y]=i;
                    incf[y]=min(incf[x],e[i].w);
                    if(!vis[y]){
                        vis[y]=1;
                        q.push(y);
                    }
                }
            }
        }
    }
    if(dis[t]==inf) return false;
    return true;
}
int cos,maxflow;
int du[N];
void upda(){
    int x=t;
    while(pre[x]){
        e[pre[x]].w-=incf[t];
        e[pre[x]^1].w+=incf[t];
        x=e[pre[x]^1].to;
    }
    cos+=incf[t]*dis[t];
    maxflow+=incf[t];
}
int num(int i,int j){
    return n+(i-1)*(n-1)+j;
}
int main(){
    rd(n);
    s=0,t=n+n*n+1;
    for(reg i=1;i<=n;++i){
        for(reg j=1;j<=n;++j){
            rd(mp[i][j]);
            if(mp[i][j]==2&&i<j){
                add(s,num(i,j),1,0);
                add(num(i,j),i,1,0);
                add(num(i,j),j,1,0);
            }else if(mp[i][j]==1){
                du[j]++;
            }
        }
    }
    int ans=n*(n-1)*(n-2)/6;
    
    for(reg i=1;i<=n;++i){
        ans-=du[i]*(du[i]-1)/2;
        for(reg j=du[i];j<=n-2;++j){
            add(i,t,1,j);
        }
    }
    while(spfa()) upda();
    ans-=cos;
    printf("%d\n",ans);
    memcpy(op,mp,sizeof mp);
    for(reg i=1;i<=n;++i){
        for(reg j=1;j<=n;++j){
            if(mp[i][j]==2&&i<j){
                int x=num(i,j);
                for(reg p=hd[x];p;p=e[p].nxt){
                    int y=e[p].to;
                    if(y!=s&&e[p].w==0){
                        if(y==j){
                            op[i][j]=1;
                            op[j][i]=0;
                        }else{
                            op[i][j]=0;
                            op[j][i]=1;
                        }
                    }
                }
            }
        }
    }
    for(reg i=1;i<=n;++i){
        for(reg j=1;j<=n;++j){
            printf("%d ",op[i][j]);
        }puts("");
    }
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2018/12/15 11:01:16
*/

总结:

值得学习的是:

1.正难则反,考虑非法的三元组,这样可以通过度数直接分开计算

2.边点转化,对无向图定向、而且贡献和点的入度有关,可以尝试采取这种策略。

3.下凸函数拆边费用流。因为下凸函数,所以最小费用的时候,每次会先选择最小的,然后往右或者往左选,那么拆边,实际上真正选择的恰好也符合实际情况。

转载于:https://www.cnblogs.com/Miracevin/p/10122842.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/107141.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 如何区别标准POE交换机和非标POE交换机[通俗易懂]

    如何区别标准POE交换机和非标POE交换机[通俗易懂]通俗的说,POE交换机就是支持网线供电的交换机,其不但可以实现普通交换机的数据传输功能还能同时对网络终端进行供电。那么,我们该如何来区别如何区别标准POE交换机和非标POE交换机呢?接下来我们就跟随飞畅科技的小编一起来详细看看吧!一、什么是POE交换机PoE供电交换机是指能够通过网线为远端受电终端提供网络供电的交换机,包含网络交换机和PoE供电两个功能,是PoE供电系统中比较常见的供电设备。二、POE交换机的分类1、标准POE交换机符合IEEE802.3af、802.3at标准,就是标准P..

    2022年10月4日
    7
  • datax(24):远程调试datax

    datax(24):远程调试datax一、datax开启远程debug1、环境本地:win10,idea专业版2020.3,datax3.0远程:CentOS6.5,datax3.02、效果3、步骤3.1远程开启debug/apps/datax/bin/datax.py/apps/datax/job/job.json-d即在后面添加-d即可,默认端口为9999,也可以自行修改datax.py文件第35行REMOTE_DEBUG_CONFIG=”-Xdebug-Xrunjdwp:transport=dt

    2022年5月17日
    127
  • VS Code 必备插件推荐「建议收藏」

    VS Code 必备插件推荐「建议收藏」插件说明备注AutoCloseTag自动添加HTML/XML关闭标签AutoRenameTag自动重命名配对的HTML/XML标签Beautify格式化代码BracketPairColorizer颜色识别匹配括号CodeRunner非常强大的一款插件…

    2022年5月6日
    74
  • 568A线序是什么_水晶头a类线序

    568A线序是什么_水晶头a类线序什么情况下会用上568A线序1985年初,计算机工业协会(CCIA)提出对大楼布线系统标准化的倡仪,美国电子工业协会(EIA)和美国电信工业协会(TIA)开始标准化制定工作。1991年7月,ANSI/EIA/TIA568即《商业大楼电信布线标准》问世。1995年底,EIA/TIA568标准正式更新为EIA/TIA/568AEIA/TIA的布线标准中规定了两种双绞线的线序568A与568B。标准568A:绿白-1,绿-2,橙白-3,蓝-4,蓝白-5,橙-6,褐白-7

    2025年6月26日
    3
  • idea 2022.01.13最新激活码(JetBrains全家桶)「建议收藏」

    (idea 2022.01.13最新激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/ide…

    2022年4月1日
    812

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号