[Contest Hunter#17-C] 舞动的夜晚
[题目链接]
[算法]
不难发现,本题是要我们求出二分图最大匹配的不可行边,我们可以将此问题转化为求可行边的补集
那么,怎样求二分图的可行边? 我们可以先来考虑一个简化的情况 : 二分图的最大匹配为完备匹配
我们求出任意一组二分图最大匹配,将匹配边(x,y)看作y到x的有向边,将非匹配(y,x)看作x到y的有向边,若x到y有增广路,则在新图G'中x到y存在路径
此时,若边(x,y)为可行边,则 :(x,y)当前为匹配边,或当前x匹配u,y匹配v,我们让x匹配y,u和v失去匹配,但我们可以找到一条从u到v的增广路
仔细观察,我们发现(x,y)为可行边等价于在新图G'上x和y在同一个强连通分量中
在本题中,并没有保证最大匹配为完备匹配,但我们可以借助网络流的源点和汇点,不妨先运行dinic算法,然后,判定条件就变成了 : 在残余网络上,
若x和y在同一个强连通分量内,则(x,y)为可行边
时间复杂度 : O(T * Sqrt(N + M)) ( 其中,Sqrt表示开方 )
[代码]
#include<bits/stdc++.h>
using namespace std;
#define MAXN 10010
#define MAXT 200010
const int inf = 2e9; struct edge
{
int to,w,id,nxt;
} e[MAXT << ]; int i,p,n,m,t,S,T,timer,tot,cnt,scc,q,w,id,top;
int head[MAXN << ],u[MAXT],v[MAXT],depth[MAXN << ],s[MAXN << ],
belong[MAXN << ],ans[MAXT],low[MAXN << ],dfn[MAXN << ];
bool flag[MAXT],instack[MAXN << ]; inline void addedge(int u,int v,int id)
{
tot++;
e[tot] = (edge){v,,id,head[u]};
head[u] = tot;
tot++;
e[tot] = (edge){u,,id,head[v]};
head[v] = tot;
}
inline bool bfs()
{
int i,l,r,u,v,w;
static int q[MAXN << ];
memset(depth,,sizeof(depth));
q[l = r = ] = S;
depth[S] = ;
while (l <= r)
{
u = q[l];
l++;
for (i = head[u]; i; i = e[i].nxt)
{
v = e[i].to;
w = e[i].w;
if (!depth[v] && w)
{
depth[v] = depth[u] + ;
q[++r] = v;
if (v == T) return true;
}
}
}
return false;
}
inline int dinic(int u,int flow)
{
int i,v,w,rest = flow,k;
if (u == T) return flow;
for (i = head[u]; i && rest; i = e[i].nxt)
{
v = e[i].to;
w = e[i].w;
if (depth[v] == depth[u] + && w)
{
k = dinic(v,min(rest,w));
if (!k) depth[v] = ;
e[i].w -= k;
e[i ^ ].w += k;
rest -= k;
}
}
return flow - rest;
}
inline void tarjan(int u)
{
int i,v,w;
low[u] = dfn[u] = ++timer;
instack[u] = true;
s[++top] = u;
for (i = head[u]; i; i = e[i].nxt)
{
v = e[i].to;
w = e[i].w;
if (!w) continue;
if (!dfn[v])
{
tarjan(v);
low[u] = min(low[u],low[v]);
} else if (instack[v]) low[u] = min(low[u],dfn[v]);
}
if (dfn[u] == low[u])
{
scc++;
do
{
v = s[top];
top--;
belong[v] = scc;
instack[v] = false;
} while (v != u);
}
}
int main()
{ scanf("%d%d%d",&n,&m,&t);
for (i = ; i <= t; i++) scanf("%d%d",&u[i],&v[i]);
tot = ;
S = n + m + ;
T = n + m + ;
for (i = ; i <= n; i++) addedge(S,i,);
for (i = ; i <= t; i++) addedge(u[i],v[i] + n,i);
for (i = ; i <= m; i++) addedge(n + i,T,);
while (bfs())
{
while (dinic(S,inf));
}
memset(flag,true,sizeof(flag));
for (p = ; p <= n; p++)
{
for (i = head[p]; i; i = e[i].nxt)
{
q = e[i].to;
w = e[i].w;
id = e[i].id;
if (q > n && q <= n + m && !w)
flag[id] = false;
}
}
for (i = ; i <= n + m + ; i++)
{
if (!dfn[i])
tarjan(i);
}
for (i = ; i <= t; i++)
{
if (belong[u[i]] == belong[v[i] + n])
flag[i] = false;
}
for (i = ; i <= t; i++)
{
if (flag[i])
ans[++cnt] = i;
}
printf("%d\n",cnt);
for (i = ; i <= cnt; i++) printf("%d ",ans[i]);
printf("\n"); return ; }
[Contest Hunter#17-C] 舞动的夜晚的更多相关文章
- CH Round #17 舞动的夜晚
舞动的夜晚 CH Round #17 描述 L公司和H公司举办了一次联谊晚会.晚会上,L公司的N位员工和H公司的M位员工打算进行一场交际舞.在这些领导中,一些L公司的员工和H公司的员工之间是互相认识的 ...
- Contest Hunter 3101
题目 Contest Hunter 3101 阶乘分解 原题传送门 题目分析 这里介绍一个本蒟蒻自己\(yy\)出来的方法. 我们发现,对于某一个单个的整数\(n\),若\(n\)能被某一个数\(x\ ...
- 2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17)
2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17) A 题意:有 n 个时刻 ...
- 2017-2018 ACM-ICPC, Central Europe Regional Contest (CERC 17)
A. Assignment Algorithm 按题意模拟即可. #include<stdio.h> #include<iostream> #include<string ...
- 【Contest Hunter【弱省胡策】Round #0-Flower Dance】组合数学+DP
题目链接: http://ch.ezoj.tk/contest/%E3%80%90%E5%BC%B1%E7%9C%81%E8%83%A1%E7%AD%96%E3%80%91Round%20%230/F ...
- Contest Hunter Round #70 - 连续两大交易事件杯省选模拟赛
orz lydrainbowcat [Problem A]「艦これ市」70万幕后交易事件 排序机器=-=.重要的是相同的处理. 我们可以从小到大添加数字,然后维护一个位置的序列.每一种相等的数字都在一 ...
- 【Contest Hunter 5302】金字塔
[原题链接]传送门 [题解思路] 1.考虑如何将序列与树相对应,想到类似dfs序和欧拉序,同一个子树对应序列连续 2.暴力分子树过于复杂,考虑简化(划重点: 若当前区间为[l,r],考虑第一颗子树所在 ...
- AtCoder Grand Contest 11~17 做题小记
原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-Grand-Contest-from-11-to-20.html UPD(2018-11-16): ...
- CH#17C 舞动的夜晚
原题链接 即求二分图的不可行边数量,因为不保证是完备匹配,所以需要通过网络流求出任意一组最大匹配,并建立新图判断. 建新图:对于跑完网络流的图上已经匹配的边,建立反边:对于没有匹配的边,建立正边(图只 ...
随机推荐
- [Windows Server 2008] 安装IIS7.5及FTP
★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频.★ 本节我们将带领大家:安装IISII ...
- dom4j.jar 的调试方法
1.将jar包的路径写在 classpath下 在cmd窗口中,查看 classpath的内容是否已经加上该路径,win7 下cmd窗口一定要是管理员身份执行 2.在D盘新建一个DOM4JWriter ...
- ZfNet解卷积:可视化CNN模型( PythonCode可视化Cifar10)
原文链接:caffe Model的可视化 snapshot: 6000 一个在线可视化小工具:http://blog.csdn.net/10km/article/details/52713 ...
- Redis防护建议
1.Redis本身防护 (1)不要使用默认端口(6379) (2)增加Redis用户名和密码 (3)在Redis绑定指定IP访问(位置配置文件[redis.config]中的bind节点)2.L ...
- BOM对象和DOM对象
一.BOM对象 BOM(Browser Object Model)是指浏览器对象模型,可以对浏览器窗口进行访问和操作.使用 BOM,开发者可以移动窗口.改变状态栏中的文本以及执行其他与页面内容不直接相 ...
- pyhon中的内存优化机制
一.变量的内存地址 python中变量的内存地址可以用id()来查看 >>> a = " >>> id(a) 2502558915696 二.pyhon中 ...
- C#学习笔记_11_方法的隐藏和重写
11_方法的隐藏和重写 方法的隐藏 需要使用到关键字:new 方法的重写 虚函数: 使用关键字virtual修饰的函数 虚函数可以被子类隐藏,也可以被子类重写 非虚函数只能被子类隐藏 关键字:over ...
- linux 头文件和库文件的设置
GCC/G++会查找系统默认的include和link的路径,以及自己在编译命令中指定的路径.自己指定的路径就不说了,这里说明一下系统自动搜索的路径. [1]include头文件路径 除了默认的/us ...
- eclipse 快捷键及使用技巧
一.程序的编译和运行的环境配置(一般不改) window -- Preferences -- Java 编译环境:Compiler 默认选中的就是最高版本. 运行环境:Installed JREs 默 ...
- 用Twebbrowser做可控编辑器与MSHTML(插入表格)
在插入表格问题上出现与结果想象不一样的问题.看代码 <table border="1" cellpadding="0" width="100%& ...