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

题面

UOJ

题解

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

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

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

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

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

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

注意一下常数问题。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define MAX 20200
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,m,ans,dg[MAX];
struct Node{int x,y;}p[MAX];
struct Line{int v,next,w,fy;}e[MAX<<2];
int h[MAX],cnt=2,cur[MAX];
inline void Add(int u,int v,int w,int fy)
{
e[cnt]=(Line){v,h[u],w,fy};h[u]=cnt++;
e[cnt]=(Line){u,h[v],0,-fy};h[v]=cnt++;
}
deque<int> Q;
int S,T,dis[MAX];
bool vis[MAX];
bool SPFA()
{
for(int i=S;i<=T;++i)dis[i]=1e9,vis[i]=false;
Q.push_back(S);dis[S]=0;vis[S]=true;
while(!Q.empty())
{
int u=Q.front();Q.pop_front();
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(!e[i].w)continue;
if(dis[v]>dis[u]+e[i].fy)
{
dis[v]=dis[u]+e[i].fy;
if(!vis[v])
{
vis[v]=true;
if(e[i].w>0)Q.push_back(v);
else Q.push_front(v);
}
}
}
vis[u]=false;
}
return dis[T]<1e9;
}
int dfs(int u,int flow)
{
if(u==T||!flow)return flow;
int ret=0;vis[u]=true;
for(int &i=cur[u];i;i=e[i].next)
{
int v=e[i].v;if(!e[i].w)continue;
if(!vis[v]&&dis[v]==dis[u]+e[i].fy)
{
int d=dfs(v,min(flow,e[i].w));
ret+=d;flow-=d;
e[i].w-=d;e[i^1].w+=d;
if(!flow){vis[u]=false;return ret;}
}
}
vis[u]=false;dis[u]=1e9;
return ret;
}
int MCMF()
{
int ret=0;
while(SPFA())
{
for(int i=S;i<=T;++i)cur[i]=h[i];
ret+=dfs(S,1e9)*dis[T];
}
return ret;
}
int f[MAX];
int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);}
int main()
{
n=read();m=read();S=0;T=n+1;
for(int i=1;i<=n;++i)p[i].x=read(),p[i].y=read();
for(int i=1;i<=n;++i)f[i]=i;
for(int i=1;i<=m;++i)
{
int u=read(),v=read();
if(1ll*p[u].x*p[v].y>1ll*p[u].y*p[v].x)swap(u,v);
int val=p[u].y>0&&p[v].y<=0;++dg[u];--dg[v];
Add(u,v,1,2*val);ans+=val;
f[getf(u)]=getf(v);vis[u]=vis[v]=true;
}
for(int i=1;i<=n;++i)if(vis[i]&&getf(i)!=getf(1)){puts("-1");return 0;}
for(int i=1;i<=n;++i)if(dg[i]&1){puts("-1");return 0;}
for(int i=1;i<=n;++i)
if(dg[i]>0)Add(S,i,dg[i]>>1,0);
else if(dg[i]<0)Add(i,T,-dg[i]>>1,0);
printf("%d\n",ans-MCMF());
return 0;
}

【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. 常见跨域解决方案以及Ocelot 跨域配置

    常见跨域解决方案以及Ocelot 跨域配置 Intro 我们在使用前后端分离的模式进行开发的时候,如果前端项目和api项目不是一个域名下往往会有跨域问题.今天来介绍一下我们在Ocelot网关配置的跨域 ...

  2. C#函数的参数传递2(ref\out)

    using System; namespace class1 { class program { static void Main(string[] args) { Console.Write(&qu ...

  3. Python中最常见的10个问题(list)

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 大熊 PS:如有需要Python学习资料的小伙伴可以加点击下方链接 ...

  4. Java生鲜电商平台-IntelliJ IDEA 最新注册码,亲测可用

    2019年IntelliJ IDEA 最新注册码(截止到2020年3月11日) 操作步骤: 第一步:  修改 hosts 文件 ~~~ 在hosts文件中,添加以下映射关系: 0.0.0.0 acco ...

  5. Java性能 -- Lock优化

    Lock / synchronized Lock锁的基本操作是通过乐观锁实现的,由于Lock锁也会在阻塞时被挂起,依然属于悲观锁   synchronized Lock 实现方式 JVM层实现 Jav ...

  6. jquery-uploadfile的使用(多文件异步上传)

    需求 在页面端可以在页面不刷新情况下上传多个有大小限制的word文件,并返回文件保存的路径,同时可以删除误上传的文件. 准备 下载该插件 该插件依赖jquery1.9.1版本(其它不清楚)*在jsp页 ...

  7. 双十一DIY装机记

    一.装机背景   最近发现古董笔记本太卡了,用了近6年,尽管自己不打游戏,但是业余时间写写代码,同时开两个编辑器,打开个大一点的软件都卡的不行,据说更换固态硬盘可以提高速度,于是乎,京东买了一个500 ...

  8. Redis中使用redis-cli及密码登录

    使用redis-cli登录后如果Redis中设置了密码那么输入密码可能会出现: NOAUTH Authentication required的错. 这个时候可以输入:auth password 进行登 ...

  9. c# 打印的问题总结

    近期 做了一个打印的类,有一下功能: /// <summary>    /// 打印数据表格的类    /// 2016/05/19 @佳序    /// 功能:    /// 01.自动 ...

  10. Linux—系统关机命令详解

    不管是重启系统还是关闭系统,首先要运行 sync 命令,把内存中的数据写到磁盘中.将数据由内存同步写入到硬盘中. [root@localhost ~]# sync 一.shutdown命令 # 立刻关 ...