Pursuit For Artifacts CodeForces - 652E
https://vjudge.net/problem/CodeForces-652E
边双啊,就是点双那个tarjan里面,如果low[v]==dfn[v](等同于low[v]>dfn[u]),表示v及其子节点只能访问到v本身,不能访问到v的祖先,那么边(u,v)是一条桥
然后再dfs一遍,不经过桥,每一次dfs得到的连通块就是一个边双。可以把一个边双缩成一个点,各个边双之间就由桥相连,得到一棵树
对于此题,可以发现,如果在一个边双内有两点a,b,还有一条边(c,d),那么一定存在一条路径从a到c经(c,d)到d再到b(不经过重复边)(好证,不证了)upd:突然发现上面那个根本就不好证明..
证明(改编自https://codeforces.com/blog/entry/14832,那个是点双的类似结论):
建一张新的网络流图。用(u,v,w)表示从u到v流量上限为w的边。
对原边双中每一条边(u,v)建新边(u,v,1),(v,u,1)。建新点S,T,建边(S,c,1),(S,d,1),(a,T,1),(b,T,1)
显然此时如果S到T的最大流是2,那么就存在要求的路径。
最大流=最小割,显然最小割是2
因此,只要一个边双内存在一条边有宝物,那么就存在不重复经过边的路径,从边双内给定点开始,到达边双内另一给定点,且拿到宝物
缩点成树后dfs即可
错误记录:
1.67行后多了一个反向加边;事实上由于70-74行的特殊写法,只要加一个方向的边即可
2.83行少了"|ok[u]"
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 #define fi first 7 #define se second 8 #define mp make_pair 9 #define pb push_back 10 typedef long long ll; 11 typedef unsigned long long ull; 12 typedef pair<int,int> pii; 13 #define N 300100 14 #define M 300100 15 struct E{int to,nxt;bool d;}; 16 namespace G 17 { 18 E e[M<<1]; 19 int f1[N],ne=1; 20 int dfn[N],dfc; 21 bool bri[M]; 22 void me(int a,int b,int c) 23 { 24 e[++ne].to=b;e[ne].nxt=f1[a];f1[a]=ne;e[ne].d=c; 25 e[++ne].to=a;e[ne].nxt=f1[b];f1[b]=ne;e[ne].d=c; 26 } 27 int dfs(int u,int last) 28 { 29 int lowu=dfn[u]=++dfc,v,lowv; 30 for(int k=f1[u];k;k=e[k].nxt) 31 { 32 v=e[k].to; 33 if(!dfn[v]) 34 { 35 lowv=dfs(v,k); 36 lowu=min(lowu,lowv); 37 if(lowv>dfn[u]) bri[k/2]=1; 38 } 39 else if(dfn[v]<dfn[u]&&k!=(last^1)) 40 lowu=min(lowu,dfn[v]); 41 } 42 return lowu; 43 } 44 int now; 45 int eccno[N],cnt,d[N]; 46 bool vis[N]; 47 void dfs2(int u) 48 { 49 eccno[u]=cnt;vis[u]=1; 50 for(int k=f1[u];k;k=e[k].nxt) 51 if(!bri[k/2]) 52 { 53 d[cnt]|=e[k].d; 54 if(!vis[e[k].to]) dfs2(e[k].to); 55 } 56 } 57 } 58 int n,m; 59 namespace T 60 { 61 using G::eccno;using G::d; 62 E e[N<<1]; 63 int f1[N],ne=1; 64 void me(int a,int b,int c) 65 { 66 e[++ne].to=b;e[ne].nxt=f1[a];f1[a]=ne;e[ne].d=c; 67 } 68 void build() 69 { 70 int i,k; 71 for(i=1;i<=n;i++) 72 for(k=G::f1[i];k;k=G::e[k].nxt) 73 if(G::bri[k/2]) 74 me(eccno[i],eccno[G::e[k].to],G::e[k].d); 75 } 76 bool ok[N]; 77 void dfs(int u,int fa) 78 { 79 ok[u]|=d[u]; 80 for(int k=f1[u];k;k=e[k].nxt) 81 if(e[k].to!=fa) 82 { 83 ok[e[k].to]|=(e[k].d|ok[u]); 84 dfs(e[k].to,u); 85 } 86 } 87 } 88 int main() 89 { 90 int i,a,b,c; 91 scanf("%d%d",&n,&m); 92 for(i=1;i<=m;i++) scanf("%d%d%d",&a,&b,&c),G::me(a,b,c); 93 G::dfs(1,-1); 94 for(i=1;i<=n;i++) if(!G::vis[i]) ++G::cnt,G::dfs2(i); 95 T::build(); 96 scanf("%d%d",&a,&b); 97 T::dfs(G::eccno[a],0); 98 puts(T::ok[G::eccno[b]]?"YES":"NO"); 99 return 0; 100 }