【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. oracle学习笔记(十九) 子程序——存储过程

    子程序--存储过程 我们可以使用子程序来封装一下我们需要的操作,子程序又有存储过程,函数和触发器. 这里先学习存储过程~ 语法 create [or replace] procedure $proce ...

  2. Python 容器使用的 5 个技巧和 2 个误区

    "容器"这两个字很少被 Python 技术文章提起.一看到"容器",大家想到的多是那头蓝色小鲸鱼:Docker,但这篇文章和它没有任何关系.本文里的容器,是 P ...

  3. [b0021] python 归纳 (七)_获得进程和线程信息

    # -*- coding: utf-8 -*- """ 获得线程, 进程 ID,NAME 总结: """ import threading ...

  4. Linux--简单实现nfs的目录挂载,ntp时间同步

    一.NFS (Network FileSystem) 网络文件系统 是FreeBSD支持的文件系统中的一种,它允许网络中的计算机之间通过TCP/IP网络共享资源. 在NFS的应用中,本地NFS的客户端 ...

  5. 最短时间(几秒内)利用C#往SQLserver数据库一次性插入10万条数据

    用途说明: 公司要求做一个数据导入程序,要求将Excel数据,大批量的导入到数据库中,尽量少的访问数据库,高性能的对数据库进行存储.于是在网上进行查找,发现了一个比较好的解决方案,就是采用SqlBul ...

  6. requests---参数关联

    在做接口测试的过程中,我们经常会遇到参数关联,也就是我们经常所说的上一个接口返回是下一个接口的请求 参数关联 在应用业务接口中,完成一个业务功能时,有时候一个接口可能不满足业务的整个流程逻辑,需要多个 ...

  7. k8s中的client-go编译成功

    要分版本的,好像1.4跟12差别好大. 1.4中用的模块管理还是vendor,12就换成mod了. 这个要记住差异. 一,从github上下载client-go的1.4版本 https://githu ...

  8. else if 使用注意

    写出一个程序,接受一个有字母和数字以及空格组成的字符串,和一个字符,然后输出输入字符串中含有该字符的个数.不区分大小写. 例如:输入:ABCDE A 输出:1 错误代码如下: #include < ...

  9. python线程类的start()和run()

    start()方法: 开始线程活动. 对每一个线程对象来说它只能被调用一次,它安排对象在一个另外的单独线程中调用run()方法,而非当前所处的线程,当该方法在同一个线程对象中被调用超过一次时,会引入R ...

  10. 【声明式事务】Spring事务介绍(一)

    事务管理对于企业应用来说是至关重要的,当出现异常情况时,它也可以保证数据的一致性. Spring事务有两种管理方式:编程式事务和声明式事务 编程式事务使用TransactionTemplate或者直接 ...