【题解】Sigitseeing Tour
题目大意
有一张$n$个结点,$m$条混合边的图($1 \leq n \leq 200$,$1 \leq m \leq 1000$),求这张图是否存在欧拉回路。
题解
因为有混合边,所以我们要先给无向边随机定向,然后再调整方向。
随机定向之后,我们就得到一张有向图。
我们记录每个结点的入度$ind[i]$和出度$outd[i]$,根据欧拉路的性质可以得到,当$ind[i] + outd[i]$为奇数时,一定不存在欧拉路。
对于建边过程,因为原有的有向边不能变向,所以我们可以忽略,只需要将读入的无向边随机定向成有向边即,设容量为$1$即可(每条边只能走一次)。
对于每一个$ind[i] \leq outd[i]$的结点$i$,我们都从源点$s$向$i$连一条有向边,容量为$\frac{outd[i] - ind[i]}{2}$;对于$ind[i] > outd[i]$的结点$i$,从$i$向$t$连一条有向边,容量为$\frac{ind[i] - outd[i]}{2}$。这两种边的含义是连接结点$i$的边中,需要变向的边数。
显然,我们从$s$开始跑一次最大流,最后判断与$s$或$t$相连的边是否满流即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue> #define MAX_N (200 + 5)
#define MAX_M (1000 + 5) using namespace std; struct Edge
{
int to;
int weight;
int next;
}; int T;
int n, m;
int s, t;
int h[MAX_N], tot = ;
Edge e[MAX_N + MAX_M << ];
int ind[MAX_N], outd[MAX_N];
int dep[MAX_N];
int cur[MAX_N];
queue <int> q;
int maxflow; inline void AddEdge(int u, int v, int w)
{
e[++tot].to = v;
e[tot].weight = w;
e[tot].next = h[u];
h[u] = tot;
return;
}; bool BFS()
{
memset(dep, 0x7f, sizeof dep);
memcpy(cur, h, sizeof cur);
q.push(s);
dep[s] = ;
int u, v, w;
while(!q.empty())
{
u = q.front();
q.pop();
for(int i = h[u]; i; i = e[i].next)
{
v = e[i].to;
w = e[i].weight;
if(dep[v] > dep[u] + && w)
{
dep[v] = dep[u] + ;
q.push(v);
}
}
}
return dep[t] != 0x7f7f7f7f;
} int DFS(int u, int flow)
{
if(u == t)
{
maxflow += flow;
return flow;
}
int v, w;
int tmp, sum = ;
for(int i = cur[u]; i && flow; i = e[i].next)
{
cur[u] = i;
v = e[i].to;
w = e[i].weight;
if(dep[v] == dep[u] + && w && (tmp = DFS(v, min(flow, w))))
{
e[i].weight -= tmp;
e[i ^ ].weight += tmp;
sum += tmp;
flow -= tmp;
}
}
return sum;
} void Dinic()
{
while(BFS()) DFS(s, 0x7f7f7f7f);
return;
} int main()
{
scanf("%d", &T);
while(T--)
{
memset(h, , sizeof h);
memset(ind, , sizeof ind);
memset(outd, , sizeof outd);
tot = ;
maxflow = ;
scanf("%d%d", &n, &m);
s = ;
t = n + ;
int u, v, d;
for(int i = ; i <= m; ++i)
{
scanf("%d%d%d", &u, &v, &d);
++outd[u];
++ind[v];
if(!d)
{
AddEdge(u, v, );
AddEdge(v, u, );
}
}
bool isEuler = true;
for(int i = ; i <= n; ++i)
{
if(ind[i] + outd[i] & )
{
isEuler = false;
break;
}
}
if(!isEuler)
{
printf("impossible\n");
continue;
}
int tmp = tot;
for(int i = ; i <= n; ++i)
{
if(ind[i] <= outd[i])
{
AddEdge(s, i, outd[i] - ind[i] >> );
AddEdge(i, s, );
}
else
{
AddEdge(i, t, ind[i] - outd[i] >> );
AddEdge(t, i, );
}
}
Dinic();
for(int i = tmp + ; i <= tot; i += )
{
if(e[i].weight)
{
isEuler = false;
break;
}
}
if(!isEuler) printf("impossible\n");
else printf("possible\n");
}
return ;
}
参考程序
【题解】Sigitseeing Tour的更多相关文章
- World Tour Finals 2019 D - Distinct Boxes 题解
太神了,专门写一篇题解 qwq 简要题意:给你 \(R\) 个红球和 \(B\) 个蓝球,你要把它们放到 \(K\) 个箱子里,要求没有两个箱子完全相同(即两种球个数就相同),求 \(K\) 的最大值 ...
- POJ2135:Farm Tour——题解
http://poj.org/problem?id=2135 题目大意: 从1到n再回来,每条边只能走一次,问最短路. —————————————————— 如果不告诉我是费用流打死不会想这个…… 我 ...
- SPOJ1825/FTOUR2:Free tour II——包看得懂/看不懂题解
http://www.spoj.com/problems/FTOUR2/en/ 题目大意:给一棵黑白染色的树,求边权和最大且经过黑点不超过K的路径. ———————————————————— 前排膜拜 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- 【SPOJ】1825. Free tour II(点分治)
http://www.spoj.com/problems/FTOUR2/ 先前看了一会题解就自己yy出来了...对拍过后交tle.................. 自己造了下大数据........t ...
- 老oj2146 && Pku2135 Farm Tour
Description When FJ's friends visit him on the farm, he likes to show them around. His farm comprise ...
- 网络流(最大流) POJ 1637 Sightseeing tour
Sightseeing tour Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 8628 Accepted: 3636 ...
- 《ACM国际大学生程序设计竞赛题解Ⅰ》——基础编程题
这个专栏开始介绍一些<ACM国际大学生程序设计竞赛题解>上的竞赛题目,读者可以配合zju/poj/uva的在线测评系统提交代码(今天zoj貌似崩了). 其实看书名也能看出来这本书的思路,就 ...
- 2013 CSU校队选拔赛(1) 部分题解
A: Decimal Time Limit: 1 Sec Memory Limit: 128 MB Submit: 99 Solved: 10 [ Submit][ Status][ Web ...
随机推荐
- CentOS7 设置电源选项,待机、睡眠、挂起
设置装有 CentOS7 的笔记本合盖后黑屏进入睡眠模式 systemd 能够处理某些电源相关的 ACPI事件,你可以通过从 /etc/systemd/logind.conf 以下选项进行配置: Ha ...
- Linux性能优化从入门到实战:12 内存篇:Swap 基础
内存资源紧张时,可能导致的结果 (1)OOM 杀死大内存CPU利用率又低的进程(系统内存耗尽的情况下才生效:OOM 触发的时机是基于虚拟内存,即进程在申请内存时,如果申请的虚拟内存加上服务器实际已用的 ...
- CA认证机制的简明解释
公钥机制面临的问题: 假冒身份发布公钥! 可以用CA来认证公钥的身份.CA有点像公安局,公钥就像身份证.公安局可以向任何合法用户颁发身份证以证明其合法身份.第三方只要识别身份证的真伪就能判断身份证持有 ...
- 装饰器模式-Decerator
一.定义 装饰器模式又叫做包装模式(Wrapper).装饰器模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 在以下情况下应该使用装饰器模式: 1.需要扩展一个类的功能,或给一个类增 ...
- Windows结束某个端口的进程
1.打开cmd命令窗口,输入命令:netstat -ano | findstr 8080,根据端口号查找对应的PID.结果如下: 发现8080端口被PID(进程号)为2188的进程占用. 2.根据PI ...
- Python全栈开发,Day3
一.基本数据类型 基础数据类型,有7种类型,存在即合理. 1.int 整数 主要是做运算的.比如加减乘除,幂,取余 + - * / ** % ... 2.bool 布尔值 判断真假以及作为条件变量 ...
- Harbor修改暴露端口
把原来的端口映射改成1180 一 修改docker-compose.yml [root@topcheer ~]# cat /mnt/harbor/docker-compose.yml version: ...
- 【HDOJ6684】Rikka with Game(博弈)
题意:有一个由小写字母组成的字符串,A和B两个人轮流操作,A想让序列的字典序最大,B想最小 两人都能任意选择一位上的字母将其右移一位(a->b,b->c……z->a)或者直接结束游戏 ...
- CSU 1551 Longest Increasing Subsequence Again(树状数组 或者 LIS变形)
题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1551 升级版:Uva 1471 题意: 让你求删除一段连续的子序列之后的LIS. 题 ...
- Linux┊详解udev
是一小部分例子,如果你的系统采用了udev方式,那你应该可以看到更多的规则.如果你想修改设备的权限或者创建信的符号连接,那么你需要熟读这些规则,特别是要仔细注意你修改的那些与之相关的设备. 修改你的u ...