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 vertices, some pairs of vertices are connected by m undirected channels. It is planned to transfer q important messages via this network, the i-th of which must be sent from vertex si to vertex di via one or more channels, perhaps through some intermediate vertices.

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 messages could be successfully transmitted.

  人生中第一道div 1 E题,值得纪念一下。

  题目就是给一个无向图,然后给每条边一个方向,问能不能满足Q个条件,每个条件就是能不能从ai到bi。

  其实不难的题目,然而没有想到双连通卡了一段时间。

  双连通的子图一定能够构造出使其满足任意两点都能互相到,所以先把原图缩点成树。

  树的话方法是对于每个条件 a->b,c=lca(a,b),然后给a-c线段的端点复制+1 -1, c-b同样,但是是维护的另一个数组。

  这样如果对于一个点维护的两个值都为正,说明不可能,否则可以。

  但是注意图可能不连通,12组数据就是这样的,被坑了一次。

代码比较乱,如下:

// ━━━━━━神兽出没━━━━━━
// ┏┓ ┏┓
// ┏┛┻━━━━━━━┛┻┓
// ┃ ┃
// ┃ ━ ┃
// ████━████ ┃
// ┃ ┃
// ┃ ┻ ┃
// ┃ ┃
// ┗━┓ ┏━┛
// ┃ ┃
// ┃ ┃
// ┃ ┗━━━┓
// ┃ ┣┓
// ┃ ┏┛
// ┗┓┓┏━━━━━┳┓┏┛
// ┃┫┫ ┃┫┫
// ┗┻┛ ┗┻┛
//
// ━━━━━━感觉萌萌哒━━━━━━ // Author : WhyWhy
// Created Time : 2015年10月11日 星期日 22时40分22秒
// File Name : B.cpp #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h> using namespace std; const int MaxN=;
const int MaxM=MaxN<<; ////////////////////////////////////////////////////// namespace TU
{ struct Edge
{
int u;
int to,next;
}; Edge E[MaxM];
int head[MaxN],Ecou;
int LOW[MaxN],DFN[MaxN];
int couBridge;
bool bridge[MaxM],cutp[MaxN];
int add_block[MaxN]; // The number of bolcks that is added by deleting a point.(not the number of blocks of this new graph!!!)
int Index; struct newEdge
{
int u,v,num; newEdge(int _u=,int _v=,int _num=):u(_u),v(_v),num(_num) {}; bool operator < (const newEdge &a) const
{
if(u==a.u)
return v<a.v; return u<a.u;
} bool operator == (const newEdge &a) const
{
return u==a.u && v==a.v;
}
}; bool chongE[MaxM]; // Parallel edge.
newEdge remE[MaxM]; void Tarjan(int u,int pre)
{
int v;
int couSon=; LOW[u]=DFN[u]=++Index; for(int i=head[u];i!=-;i=E[i].next)
{
v=E[i].to; if(v==pre) // !!!
continue; if(!DFN[v])
{
++couSon;
Tarjan(v,u); if(LOW[v]<LOW[u])
LOW[u]=LOW[v]; if(DFN[u]<LOW[v] && !chongE[i])
{
bridge[i]=;
bridge[i^]=; //
++couBridge;
}
if(u!=pre && DFN[u]<=LOW[v])
{
cutp[u]=;
++add_block[u];
}
}
else if(DFN[v]<LOW[u])
LOW[u]=DFN[v];
} if(u==pre && couSon>)
{
cutp[u]=;
add_block[u]=couSon-;
}
} void getCUTP(int n)
{
sort(remE,remE+Ecou); for(int i=;i<Ecou;++i)
if(remE[i]==remE[i-])
chongE[remE[i].num]=chongE[remE[i-].num]=; for(int i=;i<=n;++i)
if(!DFN[i])
Tarjan(i,i);
} void addEdge(int u,int v)
{
E[Ecou].u=u;
E[Ecou].to=v;
E[Ecou].next=head[u];
bridge[Ecou]=; chongE[Ecou]=;
remE[Ecou]=newEdge(u,v,Ecou); head[u]=Ecou++;
} void init(int n)
{
Ecou=couBridge=Index=; for(int i=;i<=n;++i)
{
head[i]=-;
cutp[i]=DFN[i]=add_block[i]=;
}
} }; ////////////////////////////////// int belong[MaxN];
int vis[MaxN];
int N;
int TN;
int Q; namespace TREE
{ const int LOG=; struct Edge
{
int next,to;
}; Edge E[MaxN*];
int head[MaxN],Ecou; int dep[MaxN];
int par[MaxN][LOG]; void init()
{
memset(head,-,sizeof(head));
Ecou=;
} void addEdge(int u,int v)
{
E[Ecou].next=head[u];
E[Ecou].to=v;
head[u]=Ecou++;
} int que[MaxN];
int first,last; void BFS(int root,int VI)
{
int t,v; first=last=;
dep[root]=;
par[root][]=root;
que[last++]=root; vis[root]=VI; while(last-first)
{
t=que[first++]; for(int i=;i<LOG;++i)
par[t][i]=par[par[t][i-]][i-]; for(int i=head[t];i!=-;i=E[i].next)
{
v=E[i].to; if(v==par[t][])
continue; dep[v]=dep[t]+;
par[v][]=t;
que[last++]=v; vis[v]=VI;
}
}
} int query(int u,int v)
{
if(dep[u]<dep[v])
swap(u,v); for(int det=dep[u]-dep[v],i=;det;det>>=,++i)
if(det&)
u=par[u][i]; if(u==v)
return u; for(int i=LOG-;i>=;--i)
if(par[u][i]!=par[v][i])
{
u=par[u][i];
v=par[v][i];
} return par[u][];
} // ------------- int rem1[MaxN],rem2[MaxN];
int sum1[MaxN],sum2[MaxN];
bool tvis[MaxN]; bool dfs111(int u,int pre)
{
tvis[u]=; sum1[u]=rem1[u];
sum2[u]=rem2[u]; for(int i=head[u];i!=-;i=E[i].next)
if(E[i].to!=pre)
{
if(dfs111(E[i].to,u)==) return ;
sum1[u]+=sum1[E[i].to];
sum2[u]+=sum2[E[i].to];
} if(sum1[u]> && sum2[u]> && pre!=-) return ;
return ;
} bool judge()
{
int a,b;
int c;
int VI=; for(int i=;i<=N;++i)
if(!vis[i])
BFS(i,++VI); while(Q--)
{
scanf("%d %d",&a,&b);
a=belong[a];
b=belong[b]; if(vis[a]!=vis[b]) return ; if(a!=b)
{
c=query(a,b);
++rem1[a];
--rem1[c];
++rem2[b];
--rem2[c];
}
} for(int i=;i<=N;++i)
if(tvis[i]==)
if(!dfs111(i,-))
return ;
return ;
} }; /////////////////////////////////////// int que[MaxN];
int first,last; void bfs(int u,int be)
{
first=last=;
que[last++]=u;
belong[u]=be; while(last-first)
{
u=que[first++];
for(int i=TU::head[u];i!=-;i=TU::E[i].next)
if(TU::bridge[i]== && belong[TU::E[i].to]==)
{
belong[TU::E[i].to]=be;
que[last++]=TU::E[i].to;
}
}
} void getbelong()
{
N=;
for(int i=;i<=TN;++i)
if(!belong[i])
bfs(i,++N);
} void addEdge()
{
for(int i=;i<TU::Ecou;++i)
if(TU::bridge[i])
TREE::addEdge(belong[TU::E[i].u],belong[TU::E[i].to]);
} int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout); int M;
int a,b; scanf("%d %d %d",&TN,&M,&Q); TU::init(TN);
while(M--)
{
scanf("%d %d",&a,&b);
TU::addEdge(a,b);
TU::addEdge(b,a);
}
TU::getCUTP(TN); getbelong(); TREE::init();
addEdge(); if(TREE::judge()) puts("Yes");
else puts("No"); return ;
}

(中等) CF 555E Case of Computer Network,双连通+树。的更多相关文章

  1. [Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分)

    [Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分) 题面 给出一个无向图,以及q条有向路径.问是否存在一种给边定向的方案,使得 ...

  2. 555E Case of Computer Network

    分析 一个连通块内的肯定不影响 于是我们先缩点 之后对于每个路径 向上向下分别开一个差分数组 如果两个数组同时有值则不合法 代码 #include<bits/stdc++.h> using ...

  3. 「CF555E」 Case of Computer Network

    「CF555E」 Case of Computer Network 传送门 又是给边定向的题目(马上想到欧拉回路) 然而这个题没有对度数的限制,你想歪了. 然后又开始想一个类似于匈牙利的算法:我先跑, ...

  4. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  5. Solution -「CF 555E」Case of Computer Network

    \(\mathcal{Description}\)   Link.   给定 \(n\) 个点 \(m\) 条边的无向图,判断是否有给每条边定向的方案,使得 \(q\) 组有序点对 \((s,t)\) ...

  6. CF555E Case of Computer Network

    题面:https://www.luogu.com.cn/problem/CF555E 题意:给定一张\(n\)个点\(m\)条边的无向图. 给定\(q\)组有向点对\((s,t)\). 询问是否存在使 ...

  7. 题解 CF555E Case of Computer Network

    题目传送门 题目大意 给出一个\(n\)个点\(m\)条边的无向图,有\(q\)次有向点对\((s,t)\),问是否存在一种方法定向每条边使得每个点对可以\(s\to t\). \(n,m,q\le ...

  8. [J]computer network tarjan边双联通分量+树的直径

    https://odzkskevi.qnssl.com/b660f16d70db1969261cd8b11235ec99?v=1537580031 [2012-2013 ACM Central Reg ...

  9. codeforces GYM 100114 J. Computer Network 无相图缩点+树的直径

    题目链接: http://codeforces.com/gym/100114 Description The computer network of “Plunder & Flee Inc.” ...

随机推荐

  1. (UE4) 动态加载DLL

    目前还没有实现,实在搞不懂为什么,大概代码如下: //------------------------------------------------------------------------- ...

  2. How To Install Apache Kafka on Ubuntu 14.04

    打算学习kafka ,接触一些新的知识.加油!!! 参考:https://www.digitalocean.com/community/tutorials/how-to-install-apache- ...

  3. 解决oracle数据库连接不上的问题

    今天打开部署好的java开发的网站系统,反应好慢,第一反应就是后台有问题. 查看tomcat一堆的报错信息,重启还是存在. 使用plSql连接数据库看看,登录提示如下:ORA-12514:TNS:监听 ...

  4. 获取Excel数据(或部分数据)并导出成txt文本格式

    运行代码前先导入jxl架包,以下代码仅供参考: 测试excel文件(我要获取该excel的内容为省.县.乡.村.组和PH的值): ExcelTest01类代码如下: // 读取Excel的类 impo ...

  5. 配置App真机测试证书的流程 一览

    原文链接:http://www.jianshu.com/p/6b0de0d4c925 有开发者账号的前提下, 请进行如下步骤:1.首先登录网站:https://developer.apple.com. ...

  6. publish over ssh

    http://stackoverflow.com/questions/22158092/jenkins-transferring-0-files-using-publish-over-ssh-plug ...

  7. 转:loadrunner经典面试题

    在LoadRunner中为什么要设置思考时间和pacing 答: 录制时记录的是客户端和服务端的交互,如果要精确模拟 用户的行为,那么客户操作客户端时花费了很多时间要怎么模拟呢?录入 填写提交的内容, ...

  8. Servlet程序开发--WEB开发模式(Mode I, Mode II)

    Mode I: 就是在开发中,将显示层,控制层,数据层的操作统一交给JSP或JavaBean来进行处理. 客户端通过访问JSP,调用里面的JavaBean,而通过JavaBean调用数据库,在Java ...

  9. C#调用C++动态库时类型转换

    因为本人主要从事c#开发,但是在工作中经常需要用到c++编写的DLL,因此需要知道c++中的类型与c#中的类型是如何转换的.搜集整理如下. //C++中的DLL函数原型为   //extern &qu ...

  10. list转换为map

    Java代码如下: package Test01; import java.util.ArrayList; import java.util.HashMap; import java.util.Lis ...