# [tarjan][树上差分] Codeforces 555E Case of Computer Network

## 题目描述

Andrewid the Android is a galaxy-known detective. Now he is preparing a defense against a possible attack by hackers on a major computer network.

In this network are n

To protect against attacks a special algorithm was developed. Unfortunately it can be applied only to the network containing directed channels. Therefore, as new channels can't be created, it was decided for each of the existing undirected channels to enable them to transmit data only in one of the two directions.

Your task is to determine whether it is possible so to choose the direction for each channel so that each of the q

## 输入输出格式

The first line contains three integers n

Next m

Next q

It is not guaranteed that in it initially possible to transmit all the messages.

If a solution exists, print on a single line "Yes" (without the quotes). Otherwise, print "No" (without the quotes).

## 输入输出样例

4 4 2
1 2
1 3
2 3
3 4
1 3
4 2


Yes


3 2 2
1 2
3 2
1 3
2 1


No


3 3 2
1 2
1 2
3 2
1 3
2 1


Yes

## 说明

In the first sample test you can assign directions, for example, as follows: 1→2

In the third sample test you can assign directions, for example, as follows: 1→2

# 题解

• 对于一个边双连通分量中的点，肯定是让他们能够互相到达是最优的
• 那么就先把所有边双缩起来，就变成了一棵树的定向问题
• 对于一棵树的定向，我们可以用树上差分来实现

# 代码

 1 #include <cstdio>
2 #include <iostream>
3 #include <cstring>
4 using namespace std;
5 const int N=200010;
7 bool vis[N],ins[N];
8 struct edge{int to,from;}e[N*4];
9 void insert(int x,int y)
10 {
13 }
14 void tarjan(int x,int pre)
15 {
16     bel[x]=now,dfn[x]=low[x]=++dfn[0],stack[++top]=x,ins[x]=1;
18         if (i!=(pre^1))
19             if (!dfn[e[i].to]) tarjan(e[i].to,i),low[x]=min(low[x],low[e[i].to]); else if (ins[e[i].to]) low[x]=min(low[x],dfn[e[i].to]);
20     if (dfn[x]==low[x])
21     {
22         int k=0; tot++;
23         while (k!=x) k=stack[top--],c[k]=tot,ins[k]=0;
24     }
25 }
26 void dfs(int x)
27 {
28     deep[x]=deep[fa[x][0]]+1;
29     for (int i=1;i<=18;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
30     for (int i=head[x];i;i=e[i].from) if (e[i].to!=fa[x][0]) fa[e[i].to][0]=x,dfs(e[i].to);
31 }
32 int lca(int x,int y)
33 {
34     if (deep[x]<deep[y]) swap(x,y);
35     for (int i=18;i>=0;i--) if (deep[fa[x][i]]>=deep[y]) x=fa[x][i];
36     if (x==y) return x;
37     for (int i=18;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
38     return fa[x][0];
39 }
40 void get(int x)
41 {
42     vis[x]=1;
43     for (int i=head[x];i;i=e[i].from) if (!vis[e[i].to]) get(e[i].to),f[x]+=f[e[i].to],g[x]+=g[e[i].to];
44 }
45 int main()
46 {
47     scanf("%d%d%d",&n,&m,&q);
48     for (int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),insert(x,y);
49     for (int i=1;i<=n;i++) if (!dfn[i]) now++,tarjan(i,0);
51     for (int i=2;i<=tmp;i+=2) if (c[e[i].to]!=c[e[i^1].to]) insert(c[e[i].to],c[e[i^1].to]);
52     for (int i=1;i<=tot;i++) if (!deep[i]) dfs(i);
53     for (int x,y,LCA;q;q--)
54     {
55         scanf("%d%d",&x,&y);
56         if (bel[x]!=bel[y]) { printf("No"); return 0; }
57         x=c[x],y=c[y],LCA=lca(x,y),f[x]++,f[LCA]--,g[y]++,g[LCA]--;
58     }
59     for (int i=1;i<=tot;i++) if (!vis[i]) get(i);
60     for (int i=1;i<=tot;i++) if (f[i]&&g[i]) { printf("No"); return 0; }
61     printf("Yes");
62 }

posted @ 2019-07-06 15:41  BEYang_Z  阅读(...)  评论(...编辑  收藏