codeforces #310 div1 E
算得上是比较水的E题了吧,自己想了想写了写居然1A了
对于这道题,我们很容易想到对于原图的一个边双,定向后任意两点间一定可达
那么我们可以求出原图的边双并将每个边双缩成一个点
那么原图就变成了无环的无向图,也就是一片森林
之后我们考虑每个任务:
1、如果S和T处于一个边双里,显然是可行的
2、如果S和T处于两棵树中,显然不连通不可行
3、S和T处于一棵树中,那么S->lca的所有边都是向上的,lca->T的所有边的都是向下的
对于第三种情况,我们可以在S上打一个up标记,在T上打一个down标记
之后在lca上将传递过来的up和down清除即可
那么最后我们只需要对森林做一遍DFS即可判断可行性
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<stack>
using namespace std; const int maxn=200010;
int n,m,q;
int u,v;
struct Edge{
int u,v;
}c[maxn];
int h[maxn],cnt=1;
struct edge{
int to,next;
}G[maxn<<2];
int pre[maxn],low[maxn];
int dfs_clock=0,bcc_cnt=0;
int bccno[maxn],f[maxn];
int fa[maxn],anc[maxn][20];
int dep[maxn];
int up[maxn],down[maxn];
stack<int>S; int ufs(int x){return f[x]==x?x:f[x]=ufs(f[x]);}
void add(int x,int y){++cnt;G[cnt].to=y;G[cnt].next=h[x];h[x]=cnt;}
void DFS(int u,int f){
pre[u]=low[u]=++dfs_clock;S.push(u);
for(int i=h[u];i;i=G[i].next){
if(i==(f^1))continue;
int v=G[i].to;
if(!pre[v]){
DFS(v,i);
low[u]=min(low[u],low[v]);
}else if(!bccno[v])low[u]=min(low[u],pre[v]);
}
if(low[u]==pre[u]){
bcc_cnt++;
for(;;){
int now=S.top();S.pop();
bccno[now]=bcc_cnt;
if(now==u)break;
}
}return;
}
void Get_Tree(){
for(int i=1;i<=n;++i){
if(!pre[i])DFS(i,0);
}return;
}
void Get_DFS(int u,int f){
fa[u]=f;
for(int i=h[u];i;i=G[i].next){
int v=G[i].to;
if(v==f)continue;
dep[v]=dep[u]+1;
Get_DFS(v,u);
}return;
}
void pre_LCA(){
for(int i=1;i<=n;++i){
anc[i][0]=fa[i];
for(int j=1;(1<<j)<=n;++j)anc[i][j]=-1;
}
for(int j=1;(1<<j)<=n;++j){
for(int i=1;i<=n;++i){
if(anc[i][j-1]!=-1){
int a=anc[i][j-1];
anc[i][j]=anc[a][j-1];
}
}
}return;
}
int LCA(int p,int q){
if(dep[p]<dep[q])swap(p,q);
int log;
for(log=0;(1<<log)<=dep[p];++log);log--;
for(int i=log;i>=0;--i){
if(dep[p]-(1<<i)>=dep[q])p=anc[p][i];
}
if(p==q)return p;
for(int i=log;i>=0;--i){
if(anc[p][i]!=-1&&anc[p][i]!=anc[q][i]){
p=anc[p][i];q=anc[q][i];
}
}return fa[p];
}
void check(int u,int f){
for(int i=h[u];i;i=G[i].next){
int v=G[i].to;
if(v==f)continue;
check(v,u);
up[u]+=up[v];down[u]+=down[v];
}
if(up[u]>0&&down[u]>0){
printf("No\n");
exit(0);
}return;
} int main(){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=m;++i){
scanf("%d%d",&c[i].u,&c[i].v);
add(c[i].u,c[i].v);add(c[i].v,c[i].u);
}
Get_Tree();
memset(h,0,sizeof(h));cnt=1;
for(int i=1;i<=n;++i)f[i]=i;
for(int i=1;i<=m;++i){
int a=bccno[c[i].u];
int b=bccno[c[i].v];
if(a!=b){
add(a,b);add(b,a);
int d1=ufs(a),d2=ufs(b);
if(d1!=d2)f[d1]=d2;
}
}
for(int i=1;i<=bcc_cnt;++i){
int rt=ufs(i);
if(rt==i)Get_DFS(rt,-1);
}
pre_LCA();
for(int i=1;i<=q;++i){
scanf("%d%d",&u,&v);
int a=bccno[u],b=bccno[v];
if(ufs(a)!=ufs(b)){printf("No\n");return 0;}
int lca=LCA(a,b);
up[a]++;down[b]++;up[lca]--;down[lca]--;
}
for(int i=1;i<=bcc_cnt;++i){
int rt=ufs(i);
if(rt==i)check(rt,-1);
}printf("Yes\n");return 0;
}
codeforces #310 div1 E的更多相关文章
- codeforces #310 div1 D
一开始写了个暴力模拟绳子的摆动轨迹 然后在Test 16 T掉了 后来%了一下别人的代码,发现需要对特殊情况进行特殊处理 首先我们考虑绳子的向右摆动,设当前位置为p,绳子当前长度为L 如果其旋转中心位 ...
- codeforces #310 div1 C
操作无论是U还是L,都会使原图形分裂成两个图形,且两个图形的操作互不影响 我们又发现由于操作点只可能在下斜线上,如果将操作按x排序 那么无论是U还是L,都会将操作序列完整分割成两半,且两个操作序列互不 ...
- codeforces #310 div1 B
我们考虑n-1座桥每座桥需要的长度在一个区间[L,R]中 之后我们现在有m座桥,每个桥的长度为k 题意就是要求一个匹配方案 显然如果数据范围不大直接KM就可以了 可是20w的数据KM显然要T 所以我们 ...
- codeforces #310 div1 A
首先我们考虑最暴力的拆解拼凑 显然拆分掉所有的链需要 n-m 次 之后拼凑需要 n-1 次 然后由题目规定可知:只有从1出发且连续的链不用拆掉,其余的都必须拆掉(因为两个都套有娃娃的套娃不能组合) 我 ...
- codeforces 407 div1 B题(Weird journey)
codeforces 407 div1 B题(Weird journey) 传送门 题意: 给出一张图,n个点m条路径,一条好的路径定义为只有2条路径经过1次,m-2条路径经过2次,图中存在自环.问满 ...
- codeforces 407 div1 A题(Functions again)
codeforces 407 div1 A题(Functions again) Something happened in Uzhlyandia again... There are riots on ...
- codeforces #313 div1 E
首先我们要注意到一个事情 如果一个灯塔向左覆盖,那么比他小的某个灯塔如果向左覆盖的端点大于当前塔向左覆盖的端点,他一定向右覆盖 对于当前灯塔向右覆盖也是同理 那么我们只需要记录当前覆盖到的端点就可以完 ...
- codeforces #305 div1 done
总算搞定了这一场比赛的题目,感觉收获蛮大 其中A,B,C都能通过自己的思考解决掉 D题思路好神,E题仔细想想也能想出来 以后坚持每两天或者一天做一场CF的div1的全套题目 除非有实在无法做出来的题目 ...
- Codeforces #254 div1 B. DZY Loves FFT 暴力乱搞
B. DZY Loves FFT 题目连接: http://codeforces.com/contest/444/problem/B Description DZY loves Fast Fourie ...
随机推荐
- iOS学习——iOS视频和推荐网站
最近有人问有没有iOS学习的相关资料,就简单的把自己的知道的和资源共享一下: 个人感觉iOS开发人才饱和,培训泛滥,个人推荐后台升职空间大和web前端竞争小. [链接][Ronda收集整理]2014年 ...
- 类的构造器[constructor]_C#
类的构造器(constructor): 1. 先看两个类定义: class A{ } 相当于: class A: object { Public A ( ) : base( ) { } ...
- Error LNK2001 无法解析的外部符号 的几种情况及解决办法
最近遇到的关于VS里编译出现的“无法解析的外部符号”问题,在网上寻求解决办=办法时查到下面的博客内容,作者讲解的挺全面的,作为收藏以备将来查询. 原文http://blog.csdn.net/shen ...
- CAF(C++ actor framework)(序列化之结构体,任意嵌套STL)(一)
User-Defined Data Types in Messages(用户自定义类型)All user-defined types must be explicitly “announced” so ...
- Wininet笔记一
1, InternetOpen 创建根句柄,由下一层的 InternetOpenUrl 和 InternetConnect 使用,而 InternetConnect 创建的句柄又被之后的几个函数使用. ...
- Android - 代码片段
转载说明 本篇文章可能已经更新,最新文章请转:http://www.sollyu.com/android-code-snippets/ 说明 此篇文章为个人日常使用所整理的一此代码片段,此篇文正将会不 ...
- WinForm窗体间如何传值的几种方法
(转) 窗体间传递数据,无论是父窗体操作子窗体,还是子窗体操作符窗体,有以下几种方式: 公共静态变量: 使用共有属性: 使用委托与事件: 通过构造函数把主窗体传递到从窗体中: 一.通过静态变量 特点: ...
- shell脚本编程之for语句、if语句使用介绍
介绍了shell脚本编程之for语句.if语句的使用方法. 上部: 面向过程: 顺序执行 选择执行: if, case 循环执行: for, while, until 一.for语句 格式: ...
- 【python】开始python之旅
上午开始抽空学习python,具体内容如下: (1)安装了python 2.7 (2)安装了notepad ++,安装它之前,在notepad++和Sublime Text之间纠结了一下,baidu了 ...
- DOM初涉
document documentURI, URL 返回当前网页的URL(String) activeElement 返回当前得到焦点的标签,input, textarea等比较常见,否则返回body ...