算得上是比较水的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的更多相关文章

  1. codeforces #310 div1 D

    一开始写了个暴力模拟绳子的摆动轨迹 然后在Test 16 T掉了 后来%了一下别人的代码,发现需要对特殊情况进行特殊处理 首先我们考虑绳子的向右摆动,设当前位置为p,绳子当前长度为L 如果其旋转中心位 ...

  2. codeforces #310 div1 C

    操作无论是U还是L,都会使原图形分裂成两个图形,且两个图形的操作互不影响 我们又发现由于操作点只可能在下斜线上,如果将操作按x排序 那么无论是U还是L,都会将操作序列完整分割成两半,且两个操作序列互不 ...

  3. codeforces #310 div1 B

    我们考虑n-1座桥每座桥需要的长度在一个区间[L,R]中 之后我们现在有m座桥,每个桥的长度为k 题意就是要求一个匹配方案 显然如果数据范围不大直接KM就可以了 可是20w的数据KM显然要T 所以我们 ...

  4. codeforces #310 div1 A

    首先我们考虑最暴力的拆解拼凑 显然拆分掉所有的链需要 n-m 次 之后拼凑需要 n-1 次 然后由题目规定可知:只有从1出发且连续的链不用拆掉,其余的都必须拆掉(因为两个都套有娃娃的套娃不能组合) 我 ...

  5. codeforces 407 div1 B题(Weird journey)

    codeforces 407 div1 B题(Weird journey) 传送门 题意: 给出一张图,n个点m条路径,一条好的路径定义为只有2条路径经过1次,m-2条路径经过2次,图中存在自环.问满 ...

  6. codeforces 407 div1 A题(Functions again)

    codeforces 407 div1 A题(Functions again) Something happened in Uzhlyandia again... There are riots on ...

  7. codeforces #313 div1 E

    首先我们要注意到一个事情 如果一个灯塔向左覆盖,那么比他小的某个灯塔如果向左覆盖的端点大于当前塔向左覆盖的端点,他一定向右覆盖 对于当前灯塔向右覆盖也是同理 那么我们只需要记录当前覆盖到的端点就可以完 ...

  8. codeforces #305 div1 done

    总算搞定了这一场比赛的题目,感觉收获蛮大 其中A,B,C都能通过自己的思考解决掉 D题思路好神,E题仔细想想也能想出来 以后坚持每两天或者一天做一场CF的div1的全套题目 除非有实在无法做出来的题目 ...

  9. Codeforces #254 div1 B. DZY Loves FFT 暴力乱搞

    B. DZY Loves FFT 题目连接: http://codeforces.com/contest/444/problem/B Description DZY loves Fast Fourie ...

随机推荐

  1. ios开发:OC对象的内存分析

    最近要开始准备找实习单位了,做做笔试题,看看各位大神的面试经历,发现自己要学习的东西真的还有很多,虽然也做过几个的项目,但是真正拿过笔试题一看,才发现自己对基础这方面的东西,确实有点忽视了,所以最近开 ...

  2. sql语句聚合等疑难问题收集

    ------------------------------------------------------------------------------------ 除法运算 select 500 ...

  3. Sublime Text 破解

    引言 放假三天,呆家里把win7换成了win8.1,接着玩起了hyperv,试着装了个windows xp虚拟机,体验很不错.不过对linux系统的支持不怎么样,装了个ubuntu,体验相当差!闲着无 ...

  4. Poj OpenJudge 百练 2602 Superlong sums

    1.Link: http://poj.org/problem?id=2602 http://bailian.openjudge.cn/practice/2602/ 2.Content: Superlo ...

  5. 在MAC OS X下安装usb转串口驱动(PL2303主控芯片)

    本文原创于http://www.cnblogs.com/humaoxiao,非法转载者请自重!       因为最近手里有一块STM32Discovery开发板,所以想搞一下STM32的开发,我前面的 ...

  6. linux与windows共享剪贴板(clipboard)

    linux与windows共享剪贴板(clipboard)的方法 先说两句废话,其实linux和windows之间不需要共享剪贴板,直接在putty中,按住SHIFT+鼠标选择就可以了. 但是作为一种 ...

  7. 3、WPF学习之-布局

    一.基础知识 1.所有WPF布局容器都派生自System.Windows.Controls.Panel抽象类的面板: 2.WPF种核心布局面板有StackPanel(栈面板).WrapPanel(环绕 ...

  8. Arcgis 10.1中空间连接功能

    空间链接的作用:将面上的所有点的值加起来取平均值.赋值给面属性.(我们可以定义右击——定义合并规则 连接要素的字段映射参数中指定的合并规则仅适用于连接要素中的属性,且仅适用于多个要素与目标要素匹配 ( ...

  9. js 判断页面加载状态

    //----判断当前页面是否加载状态 开始 ---- document.onreadystatechange = subSomething;//当页面加载状态改变的时候执行这个方法. function ...

  10. .net google calendar

    https://developers.google.com/gdata/client-cs http://www.codeproject.com/Articles/64474/How-to-Read- ...