【UOJ#389】【UNR#3】白鸽(欧拉回路,费用流)

题面

UOJ

题解

首先第一问就是判断是否存在一条合法的欧拉回路,这个拿度数和连通性判断一下就行了。

第二问判断转的圈数,显然我们只需要考虑顺时针过一条从源点出发的射线的次数减去逆时针过的次数就好了。

于是我们就要在欧拉回路合法的基础上算第二问。

首先如果欧拉回路合法,那么每个点的入度要等于出度,这个东西有点类似上下界网络流,即强制了每个点的度数的上下界。我们可以类似上下界网络流,先给每条边强行定向,对于入度出度差不为令的点,分别和源点和汇点连边,以追求平衡。

那么我们定向之后,边有边权,那么连一条反边,容量为\(1\),费用为边权的二倍,表示如果这条边反向则要减少的权值。

于是答案就是定向的边权和减去最小费用最大流。

注意一下常数问题。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<vector>
  8. #include<queue>
  9. using namespace std;
  10. #define ll long long
  11. #define MAX 20200
  12. inline int read()
  13. {
  14. int x=0;bool t=false;char ch=getchar();
  15. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  16. if(ch=='-')t=true,ch=getchar();
  17. while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
  18. return t?-x:x;
  19. }
  20. int n,m,ans,dg[MAX];
  21. struct Node{int x,y;}p[MAX];
  22. struct Line{int v,next,w,fy;}e[MAX<<2];
  23. int h[MAX],cnt=2,cur[MAX];
  24. inline void Add(int u,int v,int w,int fy)
  25. {
  26. e[cnt]=(Line){v,h[u],w,fy};h[u]=cnt++;
  27. e[cnt]=(Line){u,h[v],0,-fy};h[v]=cnt++;
  28. }
  29. deque<int> Q;
  30. int S,T,dis[MAX];
  31. bool vis[MAX];
  32. bool SPFA()
  33. {
  34. for(int i=S;i<=T;++i)dis[i]=1e9,vis[i]=false;
  35. Q.push_back(S);dis[S]=0;vis[S]=true;
  36. while(!Q.empty())
  37. {
  38. int u=Q.front();Q.pop_front();
  39. for(int i=h[u];i;i=e[i].next)
  40. {
  41. int v=e[i].v;if(!e[i].w)continue;
  42. if(dis[v]>dis[u]+e[i].fy)
  43. {
  44. dis[v]=dis[u]+e[i].fy;
  45. if(!vis[v])
  46. {
  47. vis[v]=true;
  48. if(e[i].w>0)Q.push_back(v);
  49. else Q.push_front(v);
  50. }
  51. }
  52. }
  53. vis[u]=false;
  54. }
  55. return dis[T]<1e9;
  56. }
  57. int dfs(int u,int flow)
  58. {
  59. if(u==T||!flow)return flow;
  60. int ret=0;vis[u]=true;
  61. for(int &i=cur[u];i;i=e[i].next)
  62. {
  63. int v=e[i].v;if(!e[i].w)continue;
  64. if(!vis[v]&&dis[v]==dis[u]+e[i].fy)
  65. {
  66. int d=dfs(v,min(flow,e[i].w));
  67. ret+=d;flow-=d;
  68. e[i].w-=d;e[i^1].w+=d;
  69. if(!flow){vis[u]=false;return ret;}
  70. }
  71. }
  72. vis[u]=false;dis[u]=1e9;
  73. return ret;
  74. }
  75. int MCMF()
  76. {
  77. int ret=0;
  78. while(SPFA())
  79. {
  80. for(int i=S;i<=T;++i)cur[i]=h[i];
  81. ret+=dfs(S,1e9)*dis[T];
  82. }
  83. return ret;
  84. }
  85. int f[MAX];
  86. int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);}
  87. int main()
  88. {
  89. n=read();m=read();S=0;T=n+1;
  90. for(int i=1;i<=n;++i)p[i].x=read(),p[i].y=read();
  91. for(int i=1;i<=n;++i)f[i]=i;
  92. for(int i=1;i<=m;++i)
  93. {
  94. int u=read(),v=read();
  95. if(1ll*p[u].x*p[v].y>1ll*p[u].y*p[v].x)swap(u,v);
  96. int val=p[u].y>0&&p[v].y<=0;++dg[u];--dg[v];
  97. Add(u,v,1,2*val);ans+=val;
  98. f[getf(u)]=getf(v);vis[u]=vis[v]=true;
  99. }
  100. for(int i=1;i<=n;++i)if(vis[i]&&getf(i)!=getf(1)){puts("-1");return 0;}
  101. for(int i=1;i<=n;++i)if(dg[i]&1){puts("-1");return 0;}
  102. for(int i=1;i<=n;++i)
  103. if(dg[i]>0)Add(S,i,dg[i]>>1,0);
  104. else if(dg[i]<0)Add(i,T,-dg[i]>>1,0);
  105. printf("%d\n",ans-MCMF());
  106. return 0;
  107. }

【UOJ#389】【UNR#3】白鸽(欧拉回路,费用流)的更多相关文章

  1. UOJ #455 [UER #8]雪灾与外卖 (贪心、模拟费用流)

    题目链接 http://uoj.ac/contest/47/problem/455 题解 模拟费用流,一个非常神奇的东西. 本题即为WC2019 laofu的讲课中的Problem 8,经典的老鼠进洞 ...

  2. hdu4067 费用流(混合欧拉的宽展和延伸)

    题意:        给以一个图,每个有向边都有两个权值,a,b其中a是保留这条边的花费,b是删除这条边的花费,让你删去一些边使图满足一下要求: (1)只有一个起点和一个终点 (2)所有的边都是又向的 ...

  3. hdu-5988 Coding Contest(费用流)

    题目链接: Coding Contest Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Ot ...

  4. POJ2195 Going Home[费用流|二分图最大权匹配]

    Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22088   Accepted: 11155 Desc ...

  5. BZOJ3130: [Sdoi2013]费用流[最大流 实数二分]

    3130: [Sdoi2013]费用流 Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 960  Solved: 5 ...

  6. 洛谷 1004 dp或最大费用流

    思路: dp方法: 设dp[i][j][k][l]为两条没有交叉的路径分别走到(i,j)和(k,l)处最大价值. 则转移方程为 dp[i][j][k][l]=max(dp[i-1][j][k-1][l ...

  7. Codeforces 730I [费用流]

    /* 不要低头,不要放弃,不要气馁,不要慌张 题意: 给两行n个数,要求从第一行选取a个数,第二行选取b个数使得这些数加起来和最大. 限制条件是第一行选取了某个数的条件下,第二行不能选取对应位置的数. ...

  8. zkw费用流+当前弧优化

    zkw费用流+当前弧优化 var o,v:..] of boolean; f,s,d,dis:..] of longint; next,p,c,w:..] of longint; i,j,k,l,y, ...

  9. 【BZOJ-4213】贪吃蛇 有上下界的费用流

    4213: 贪吃蛇 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 58  Solved: 24[Submit][Status][Discuss] Desc ...

随机推荐

  1. C# 通过反射调用 Func 委托

    C# 通过反射调用 Func 委托 Intro 最近我的 NPOI 扩展库增加了,自定义输出的功能,可以自定义一个 Func 委托来设置要导出的内容,详细介绍请查看 https://www.cnblo ...

  2. GO基础之函数

    一.Go语言函数的格式 函数构成了代码执行的逻辑结构,在Go语言中,函数的基本组成为:关键字 func.函数名.参数列表.返回值.函数体和返回语句,每一个程序都包含很多的函数,函数是基本的代码块. 函 ...

  3. JS基础语法---分支语句之:if语句,if-else语句,if-ever if语句

    //if语句只有一个分支 //if-else语句有两个分支,最终执行一个分支 //if-else if-else if-else if-else if..........else---多分支,最终也是 ...

  4. 「SAP技术」SAP不够严谨?

    SAP不够严谨? 大家知道采购业务里,有一种特殊的采购形式,就是按单采购,意思是所采购的物料只用于指定的销售订单的销售出库.这种业务场景在SAP项目实践中,比较常见. 强大无比的SAP系统当然有解决方 ...

  5. 0基础入门学习Python(第4章)

    第四章,了不起的分支和循环 4.1 分支和循环 Python主要依靠缩进来区分代码块 4.2 快速上手 成绩按照分数来划分等级,90分以上为A,80~90 为B,60~80 为C,60以下为D p4_ ...

  6. kali linux查看局域网下所有IP,并对指定IP实施局域网内攻击(断网,随时查看对方密码,上网痕迹等)

    首先我们打开我们熟悉的kali linux操作系统,利用指令: ifconfig 来确认本机的ip地址 确认了本机的ip地址之后,利用一下的指令查看局域网下所有ip: fping -g 本机IP地址/ ...

  7. qt 使用OpenCV

    使用MinGW编译OpenCV源码 下载OpenCV源码.CMake编译工具 编译安装完: Qt工程配置 INCLUDEPATH += D:/qt_work/opencv/build/install/ ...

  8. 彻底解决Python3写爬虫或网站时的乱码问题

    第一次写贴子,试试水 很多玩Python3的都会遇到编码问题,如果直接去处理未知编码的网页,不是Python内部编码格式utf8会出现乱码,下面介绍一种将未知编码的字串转换为utf8来避免乱码的方法, ...

  9. [b0042] python 归纳 (二七)_gui_tkinter_基本使用

    # -*- coding: utf-8 -*- """ 学习 Tkinter画图基本控件使用 逻辑: 放几个 输入控件.点击按钮,将输入控件内容打印出来 使用: 1. 创 ...

  10. 渗透测试学习 十五、 文件上传&&解析漏洞

    大纲:文件解析漏洞 上传本地验证绕过 上传服务器验证绕过 文件解析漏洞 解析漏洞主要说的是一些特殊文件被IIS.Apache.Nginx在某些情况下解释成脚本文件格式的漏洞. IIS 5.x/6.0解 ...