【题目链接】
  http://uoj.ac/problem/389
【题解】
  首先存在欧拉回路的条件是所有非孤立点都与一号点连通,并且每个点的度数都是偶数。
  一个简单的想法,把每条边绕原点旋转在的角度记为这条边的费用(如果是负的就把这条边反向),我们先把所有的费用都加在一起作为初始的答案。那么显然会有一些点的度数不符合条件。考虑费用流,对于一条边 (u,v) ( u , v ) (u,v)我们从 u u u向v" role="presentation" style="position: relative;">vvv连一条费用为 2∗这条边费用 2 ∗ 这 条 边 费 用 2*这条边费用的边,表示将这条边反向。对于 入度>出度 入 度 > 出 度 入度>出度的点,从 S S S向这个点连费用是1,流量为(入度−出度)/2" role="presentation" style="position: relative;">(入度−出度)/2(入度−出度)/2(入度-出度)/2, 出度>入度 出 度 > 入 度 出度>入度的点向 T T T连边。跑最小费用流即可。
由于边权不一定为整数,费用流会跑的比较慢。由于绕的圈数一定是整数,所以可以用射线法:从原点射出一条射线,如果边从左到右跨过费用为1,反之为-1。在新图上做费用流答案就费用是整数了。
费用流的话,每次spfa求出最短路图,在最短路图上用dinic增广即可。
时间复杂度:O(NM)" role="presentation" style="position: relative;">O(NM)O(NM)O(NM)?,反正跑的挺快的。
【代码】

# include <bits/stdc++.h>
# define    N     100010
# define    ll    long long
# define    inf     0x3f3f3f3f
# define    eps     1e-7
using namespace std;
int read(){int tmp = 0, fh = 1; char ch = getchar();while (ch < '0' || ch > '9'){if (ch == '-') fh = -1; ch = getchar();}while (ch >= '0' && ch <= '9'){tmp = tmp * 10 + ch - '0'; ch = getchar();}return tmp * fh;
}
const double pi = acos(-1.0);
struct Node{int data, next, l, re;double vote;
}e[N];
struct Edge{int u, v;
}eg[N];
struct Point{double x, y;
}p[N];
int n, m, deg[N], use[N], place, head[N], q[N], frm[N], now[N], step[N];
int dis[N], ans;
void buildedge(int u, int v, int w){e[++place].data = v; e[place].next = head[u]; head[u] = place; e[place].l = w;
}
void build(int u, int v, int l, double w){e[++place].data = v; e[place].next = head[u]; head[u] = place; e[place].l = l; e[place].vote = w; e[place].re = place + 1;e[++place].data = u; e[place].next = head[v]; head[v] = place; e[place].l = 0; e[place].vote = -w; e[place].re = place - 1;
}
double cross(Point x, Point y){ return x.x * y.y - x.y * y.x; }
double dot(Point x, Point y){ return x.x * y.x + x.y * y.y; }
void dfs(int x){for (int ed = head[x]; ed != 0; ed = e[ed].next)if (use[e[ed].l] == false){use[e[ed].l] = true;if (step[e[ed].data] == false){step[e[ed].data] = true;dfs(e[ed].data);}}
}
double sqr(double x){return x * x;
}
inline bool spfa(int S, int T){for(int i = S; i <= T; i++) dis[i] = inf, use[i] = 0;dis[T] = 0; use[T] = 1;deque <int> q; q.push_back(T);while(!q.empty()){int now=q.front();q.pop_front();for(int k=head[now];k != 0;k = e[k].next) if(e[e[k].re].l > 0 && dis[e[k].data] > dis[now] - e[k].vote){dis[e[k].data] = dis[now] - e[k].vote;if(!use[e[k].data]){use[e[k].data] = true;if(!q.empty() && dis[e[k].data] < dis[q.front()])q.push_front(e[k].data);else q.push_back(e[k].data);}}use[now]=0;}return dis[S] < inf;
}
void bfs(int S, int T){for(int i = S; i <= T; i++) step[i] = inf;int pl = 1, pr = 1; q[1] = S, step[S] = 0;while (pl <= pr && step[T] == inf){int x = q[pl++];for (int ed = head[x]; ed != 0; ed = e[ed].next)if (e[ed].l > 0 && step[e[ed].data] == inf && dis[x] - e[ed].vote == dis[e[ed].data]){q[++pr] = e[ed].data;step[e[ed].data] = step[x] + 1;}}
}
inline int dfs(int x, int low, int T){if(x == T) return low;int used = 0, a;for(int ed = now[x]; ed != 0; ed = e[ed].next)if(e[ed].l > 0 && dis[x] - e[ed].vote == dis[e[ed].data] && step[x] + 1 == step[e[ed].data]){a = dfs(e[ed].data, min(e[ed].l, low - used), T);if(a) ans -= a * e[ed].vote, e[ed].l -= a, e[e[ed].re].l += a, used += a;if(used == low){now[x] = ed;return used; }}now[x] = 0;return used;
}
int costflow(int S, int T){int flow = 0;while(spfa(S, T)){for (bfs(S, T); step[T] != inf; bfs(S, T)){for (int i = S; i <= T; i++) now[i] = head[i];flow += dfs(S, inf, T);}}return flow;
}
int met(Point x, Point y){if (x.x * y.x >= 0) return 0;double num = (0 - x.x) / (y.x - x.x) * (y.y - x.y) + x.y;return num > 0;
}
int main(){n = read(), m = read();for (int i = 1; i <= n; i++)p[i].x = read(), p[i].y = read();for (int i = 1; i <= m; i++){eg[i].u = read(), eg[i].v = read();buildedge(eg[i].u, eg[i].v, i);buildedge(eg[i].v, eg[i].u, i);deg[eg[i].u]++, deg[eg[i].v]++;}for (int i = 1; i <= n; i++){if (deg[i] % 2 == 1){printf("%d\n", -1);return 0;}}dfs(1);for (int i = 1; i <= m; i++)if (use[i] == false){printf("%d\n", -1);return 0;}memset(head, 0, sizeof(head)); place = 0;memset(deg, 0, sizeof(deg));int S = 0, T = n + 1, num = 0;for (int i = 1; i <= m; i++){if (cross(p[eg[i].u], p[eg[i].v]) < 0) swap(eg[i].u, eg[i].v);if (met(p[eg[i].u], p[eg[i].v]) == 1) num = 1; else num = 0;ans = ans + num;deg[eg[i].u]--, deg[eg[i].v]++;build(eg[i].u, eg[i].v, 1, num * 2);}for (int i = 1; i <= n; i++)if (deg[i] > 0)build(i, T, deg[i] / 2, 0);else build(S, i, -deg[i] / 2, 0);costflow(S, T);printf("%d\n", ans);
}

[uoj389][UNR #3]白鸽【欧拉回路】【射线法】【费用流】相关推荐

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

    [UOJ#389][UNR#3]白鸽(欧拉回路,费用流) 题面 UOJ 题解 首先第一问就是判断是否存在一条合法的欧拉回路,这个拿度数和连通性判断一下就行了. 第二问判断转的圈数,显然我们只需要考虑顺 ...

  2. 射线法 java_射线法(1190 - Sleepwalking )

    题目:http://lightoj.com/volume_showproblem.php?problem=1190 参考链接:https://blog.csdn.net/gkingzheng/arti ...

  3. c#竖直射线法判断点是否再多边形里面

    一.开发环境: VS2017   C#winform 二.竖直射线法大致介绍 通过被判断的点P(x0,y0)引出竖直的上下两条射线,如果两条射线与多变形的交点都为奇数个,那么这个点再多边形里面,反之, ...

  4. python 判断一个点(坐标)是否在一个多边形内利用射线法

    看了一篇博客写的用射线法判断一个经纬度点是否在一个多边形的内部的方法 经验证可行所以拿来用作备份: class Point:lng = ''lat = ''def __init__(self, lng ...

  5. python内点法_python射线法判断一个点在图形区域内外

    # -*-encoding:utf-8 -*- # file:class.py # """ 信息楼 0 123.425658,41.774177 1 123.425843 ...

  6. 射线法进行地理空间坐标计算

    移动端应用开发过程中经常需要计算地理空间关系,例如:快递员/外卖员是否已抵达小区附近,办公打卡签到时是否在公司周边,共享单车是否停放在指定区域或禁停区等等. 前面我们介绍过如何使用MySQL进行地理坐 ...

  7. JAVA射线_射线法 - 萌德真帅 - 博客园

    射线法 这是一个大佬看了都说简单的算法....(甚至觉得没有掌握的必要) QAQ 这个算法是用来判断一个点是否在一个多边形以内.很简单 将这个点沿着x轴的正方向作射线.如果穿过的边数为基数,那么这个点 ...

  8. python射线法-离线根据经纬度反向获取城市信息

    python射线法-离线根据经纬度反向获取城市信息 准备工作 相关算法储备 总结 目前能够使用 经纬度信息去逆解析经纬度的API有很多,各自可以根据业务需求和地理编码格式选择百度.谷歌.高德等API. ...

  9. 判断坐标点是否处于某个范围内(射线法)

    判断坐标点是否处于某个范围内(射线法) Vue Java 声明 Vue /*** 判断点是否多边形内* @param {Point} point 点对象* @param {Polyline} poly ...

最新文章

  1. 近期活动盘点:数据化思维困局和0.01突破讲座、极简大数据决策,培养数据化思维讲座...
  2. 【解决方案】本次安装Visual Studio 所用的安装程序不完整
  3. 使用uni-app开发微信小程序之登录模块
  4. 精选30张炫酷的动态交互式图表,Pandas一键生成,通俗易懂
  5. CSS3中使用translate() 方法实现元素位置的移动
  6. 第二部分Calendar原理和思想
  7. Pandas知识点-Series数据结构介绍
  8. VUE 调试神器 vue-devtools
  9. Linux的进程/线程/协程系列4:进程知识深入总结:上篇
  10. (转) Hibernate注解开发
  11. 计算机中定义事物各种特点的术语,计算机科学中具有特殊含义或易溷淆的术语辨析(2版).doc...
  12. 深度学习课程笔记(十三)深度强化学习 --- 策略梯度方法(Policy Gradient Methods)...
  13. springMVC 理解大综合
  14. nutch2.3 mysql教程_Nutch2.2.1+MySQL+Solr4.10.3安装部署
  15. android app跳转到微信
  16. kibana报表展示
  17. TMS320F28335与10位数模转换器TLC5615的SPI通讯问题2(数模转换芯片TLC5615 原理篇)
  18. 浏览器的作用不只是搜索、浏览网页,它还隐藏着这些功能
  19. 2023真无线蓝牙耳机怎么选?值得入手的蓝牙耳机推荐
  20. 解决minGW32-make 编译opencv时 error: ‘std::_hypot‘ has not been declared using std::hypot;

热门文章

  1. k-means算法可视化
  2. 【每日一读】Towards Understanding the Instability of Network Embedding
  3. Latent Semantic Analysis
  4. Mac命令行方式格式化U盘
  5. 如何在程序中获得其他程序的 图标?
  6. python和网络运维_网络工程师的Python之路:网络运维自动化实战
  7. 什么是配电室智能运维?它有哪些功能应用?
  8. MySQL-基础代码(部分)+思维导图
  9. 微信支付宝积极推广刷脸支付行业会快速跟进
  10. 重磅回归-SSM整合进阶项目实战之个人博客系统