题干:

小p和他的朋友约定好去游乐场游玩,但是他们到了游乐场后却互相找不到对方了。
游乐场可以看做是一张n个点,m条道路的图,每条道路有边权wi,表示第一次经过该道路时的花费(第二次及以后经过时花费为0)。
现在,小p要去找他的朋友,但他的朋友行踪很诡异,小p总是要遍历完这n个点才能找到他,同时小p希望总花费最小。
找到朋友的方案可能不唯一(具体看样例解释),小p想知道在这所有的方案中,有多少条边在每个方案中都会被经过。

输入描述:

第一行两个整数n, m. p,分别表示点数,边数,小p的初始位置。
接下来m行,每行两个整数u, v, w表示从u到v有一条无向边,边权为w。

输出描述:

输出一个整数k,表示必须经过的边的数量。

示例1

输入

复制

5 7 1
1 2 3
2 3 7
1 3 5
2 4 2
1 5 3
5 4 3
2 5 3

输出

复制

2

说明

 

样例解释:


几种可能的方案如下:
1−2−4−5−4−2−1−31−2−4−5−4−2−1−3
1−5−4−2−4−5−1−31−5−4−2−4−5−1−3
1−3−1−2−5−2−41−3−1−2−5−2−4
1−2−5−2−4−2−5−2−4−2−5−2−4⋯−2−5−2−4−2−1−31−2−5−2−4−2−5−2−4−2−5−2−4⋯−2−5−2−4−2−1−3
可以证明,4 - 2和1 - 3这两条边在所有方案中都被经过。
(以上每种方案的总花费均为13,同时可以证明没有比这更优的策略)

示例2

输入

复制

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

输出

复制

2

示例3

输入

复制

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

输出

复制

0

备注:

 

2⩽n<m⩽2∗105,1⩽边权⩽1062⩽n<m⩽2∗105,1⩽边权⩽106

保证图联通,保证无自环,保证无重边

解题报告:

好难的题,,不会证明但是倒是想明白了AC代码2那里为什么else if(i!=(lstedge^1)) low[x]=min(low[x],dfn[y]);这里不能写成 low[x]=min(low[x],low[y]);因为你想啊(虽然这个题能过)。

按照这个边的顺序访问节点,那么当访问边7的时候,LOW[3]已经变成了2,所以如果那样写,那LOW[6]也变成了2.看起来是没什么问题,但是我们看回溯到3这个节点的时候(注意这时候还没访问3->6这条边,刚刚那是6节点开始的6->3这条边),他需要开始看能否把4节点这一支分出去当成一个子图了,发现不行,因为DFN[4]=2(这本是不对的,但是托了3->2这条边优先访问的福啊!就把状态弄成这样了)然后再遍历3->6这个节点,发现也不行,因为DFN[6]=2,然后无奈返回,并且不标记成是个割点,,但是很显然,3这个点就是个割点!!!这就是为什么板子要这么写!!

对于题目:

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=200050;
int root,sum=1,dfn[maxn],low[maxn],ans[maxn],f[maxn];
int getf(int u){return f[u]==u?u:f[u]=getf(f[u]);}
struct Ed{int u,v,w;bool operator<(const Ed &A)const{return w<A.w;
}
}E[maxn];
struct Edge{int v,id,next;}e[maxn*2];
int first[maxn],tot;
void add(int u,int v,int id){e[tot].v=v;e[tot].id=id;e[tot].next=first[u];first[u]=tot++;
}
void tarjin(int u,int last){dfn[u]=low[u]=sum++;for(int i=first[u];~i;i=e[i].next){int v=e[i].v;if(i==(1^last))continue;if(dfn[v]){low[u]=min(low[u],dfn[v]);}else{tarjin(v,i);low[u]=min(low[u],low[v]);if(low[v]>dfn[u])ans[e[i].id]=1;}}
}
int main(){int i,j,n,m,p,u,v,w;scanf("%d%d%*d",&n,&m);tot=0;memset(first,-1,sizeof(first));for(i=1;i<=n;++i)f[i]=i;for(i=0;i<m;++i){scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].w);}sort(E,E+m);for(i=0;i<m;++i){j=i;while(j+1<m&&E[j+1].w==E[i].w)j++;tot=0;for(int k=i;k<=j;++k){int fu=getf(E[k].u),fv=getf(E[k].v);if(fu!=fv){add(fu,fv,k);add(fv,fu,k);}}for(int k=i;k<=j;++k){int fu=getf(E[k].u),fv=getf(E[k].v);if(fu==fv || dfn[fu]) continue;tarjin(fu,-1);}for(int k=i;k<=j;++k){int fu=getf(E[k].u),fv=getf(E[k].v);if(fu==fv)continue;first[fu]=first[fv]=-1;dfn[fu]=dfn[fv]=0;f[fu]=fv;}i=j;}int h=0;for(i=0;i<m;++i)h+=ans[i];cout<<h<<endl;return 0;
}

AC代码2:

#include<bits/stdc++.h>
using namespace std;
#define maxn 200001
#define maxm 300001
struct edge
{int a,b,c;int id;inline void read(int _id){scanf("%d%d%d",&a,&b,&c);id=_id;}bool operator <(const edge &p)const{return c<p.c;}
}e[maxm];
int n,m;
inline void init()
{int p;scanf("%d%d",&n,&m);scanf("%d",&p);for(int i=1;i<=m;i++) e[i].read(i);sort(e+1,e+m+1);
}
int head[maxn],nxt[maxm<<1],ver[maxm<<1],id[maxm<<1],tot;
inline void addedge(int a,int b,int _id)
{nxt[++tot]=head[a];ver[tot]=b;id[tot]=_id;head[a]=tot;nxt[++tot]=head[b];ver[tot]=a;id[tot]=_id;head[b]=tot;
}
int ans[maxm];int dfn[maxn],low[maxn],cnt;
inline void tarjan(int x,int lstedge)
{dfn[x]=low[x]=++cnt;for(int i=head[x];i;i=nxt[i]){int y=ver[i];if(!dfn[y]){tarjan(y,i);low[x]=min(low[x],low[y]);if(low[y]>dfn[x]) ans[id[i]]=666;}else if(i!=(lstedge^1)) low[x]=min(low[x],dfn[y]);}
}
int fa[maxn];inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
int main()
{init();for(int i=1;i<=n;i++) fa[i]=i;int Nowedge=1;while(Nowedge<=m){int L=Nowedge,R=Nowedge;while(R+1<=m&&e[R].c==e[R+1].c) R++;Nowedge=R+1;cnt=0;tot=1;for(int i=L;i<=R;i++){int a=find(e[i].a),b=find(e[i].b);head[a]=0;head[b]=0;dfn[a]=dfn[b]=low[a]=low[b]=0;}for(int i=L;i<=R;i++){int a=find(e[i].a),b=find(e[i].b);if(a==b){ans[e[i].id]=-1;continue;}ans[e[i].id]=233;addedge(a,b,e[i].id);}for(int i=L;i<=R;i++){if(!dfn[find(e[i].a)]) tarjan(find(e[i].a),0);if(!dfn[find(e[i].b)]) tarjan(find(e[i].b),0);}for(int i=L;i<=R;i++) fa[find(e[i].a)]=find(e[i].b);}int ttl = 0;for(int i=1;i<=m;i++){if(ans[i]==666) ttl++;}cout<<ttl<<endl;return 0;
}

AC代码3:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
struct edge{int f,to,v;}a[N];
struct node{int to,id;};
bool cmp(edge a,edge b){return a.v<b.v;}
int fa[N];vector<node>g[N];
int dfn[N],low[N],num;int ans[N];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void unite(int x,int y){x=find(x),y=find(y),fa[x]=y;}
void tarjan(int x,int fa){dfn[x]=low[x]=++num;for(auto it:g[x]){int u=it.to,id=it.id;if(id==fa) continue;if(!dfn[u]){tarjan(u,id);low[x]=min(low[x],low[u]);if(dfn[x]<low[u]) ans[id]=1;}else low[x]=min(low[x],dfn[u]);}
}
int main(){int n,m,q,x,y,c;scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].f,&a[i].to,&a[i].v);sort(a+1,a+m+1,cmp);for(int i=1;i<=n;i++) fa[i]=i;for(int i=1;i<=m;i++){int s=i;while(a[i+1].v==a[i].v) i++;for(int j=s;j<=i;j++){x=find(a[j].f),y=find(a[j].to);if(x==y) continue;     g[x].push_back({y,j});g[y].push_back({x,j});}for(int j=s;j<=i;j++){x=find(a[j].f),y=find(a[j].to);if(x==y||dfn[x]) continue;tarjan(x,0);}for(int j=s;j<=i;j++){x=find(a[j].f),y=find(a[j].to);dfn[x]=dfn[y]=0;g[x].clear(),g[y].clear();unite(x,y);}num=0;}int out=0;for(int i=1;i<=m;i++) if(ans[i]) out++;printf("%d\n",out);return 0;
}

【牛客 - 272D】Where are you(Tarjan求桥)相关推荐

  1. 牛客小白月赛6 水题 求n!在m进制下末尾0的个数 数论

    链接:https://www.nowcoder.com/acm/contest/135/C 来源:牛客网 题目描述 其中,f(1)=1;f(2)=1;Z皇后的方案数:即在Z×Z的棋盘上放置Z个皇后,使 ...

  2. 【牛客网 - 华为机试 - HJ15 求int型正整数在内存中存储时1的个数】

    描述 输入一个 int 型的正整数,计算出该 int 型数据在内存中存储时 1 的个数. 数据范围:保证在 32 位整型数字范围内 输入描述: 输入一个整数(int类型) 输出描述: 这个数转换成2进 ...

  3. C++初阶习题(牛客网)【5】求字符串最后一个单词的长度

    题目描述: 牛客网题目链接 HJ1 字符串最后一个单词的长度 描述: 计算字符串最后一个单词的长度,单词以空格隔开,字符串长度小于5000.(注:字符串末尾不以空格为结尾) 输入描述: 输入一行,代表 ...

  4. 【Gym - 101986F】Pizza Delivery(Dijkstra最短路,建图方式,反向建图,Tarjan求桥,图论模板)

    题干: 题目大意: 一个有向图,编号1~n的n个点,m条边,规定1为起点,2为终点,问对于每一条边,反转它的方向,最短路会不会发生改变,如果变短了,输出HAPPY,变长了或者到达不了了输出SAD,不变 ...

  5. tarjan求桥、割顶

    若low[v]>dfn[u],则(u,v)为割边.但是实际处理时我们并不这样判断,因为有的图上可能有重边,这样不好处理.我们记录每条边的标号(一条无向边拆成的两条有向边标号相同),记录每个点的父 ...

  6. 8/21 牛客补题+cf思维+tarjan

    P3398 仓鼠找 sugar 题意:在一棵树上,给定四个点,在a和b的最短路径中能否在c和d的最短路径中相遇. 思路:可看出题目给了伪标签,不是tarjan的题.一道倍增lca的题. 1.若要满足相 ...

  7. <数据库> 牛客SQL54 去掉最大最小值 再求均值

    描述 查找排除最大.最小salary之后的当前(to_date = '9999-01-01' )员工的平均工资avg_salary. CREATE TABLE `salaries` ( `emp_no ...

  8. 牛客练习赛 25 E题 定向 【桥 + 思维】 无向图定方向变强连通图

    传送门 题意: 给定一个无向图, 然后你要给这幅图每条边加上一个方向, 使得这个图是有向图强连通 思路: 关键在于如何判断无解的情况, 如果能保证当前的图有解, 那么直接dfs一下就可以出答案. 仔细 ...

  9. 洛谷or牛客数据结构+算法

    栈思想:先进后出 tips:栈里能放下标就放下标 (牛客)小c的计事本(直接用stack可以简化代码,且不会被自己绕晕,当时没意识到) (牛客)吐泡泡(没意识到用栈),(牛客)好串 1.后缀表达式(栈 ...

最新文章

  1. Oracle 外连接和 (+)号的用法
  2. LeetCode 第 198 场周赛(434/5778,前7.51%)
  3. cobbler介绍与部署
  4. android权威指南十三章,《Android编程权威指南》第30~32以及第34章读书笔记
  5. Visual Studio 2019 16.1 正式发布,更快更高效
  6. cesium 百度地图_Cesium专栏-热力图(附源码下载)
  7. python结巴分词代码_结巴分词Python代码
  8. wd移动硬盘不能识别_wd移动硬盘读不出来怎么办
  9. 用C++写洛谷P1427小鱼的数字游戏
  10. 计算机的键盘组合件,电脑组合键盘快捷键大全
  11. eclipes代码提示及防空格自动补全
  12. 买一台服务器到底能干什么?可用于这7点!
  13. 基于离散小波变换 (DWT)的图像信息隐藏算法
  14. 职场修炼--你开口说话的境界在第几层?
  15. python 连接mssqlserver方法之pymssql
  16. Android解决你的手机上未安装应用程序。的问题
  17. 算法一 knn 扩展 BBF算法,在KD-tree上找KNN ( K-nearest neighbor)
  18. html5魔塔编辑器安卓版,Mota: 纪元魔塔前传。童年魔塔记忆。使用手机编写的5000行代码...
  19. Matlab学习-图像处理工具箱函数
  20. 【Golang】-微信二次分享及Js Sdk签名工具

热门文章

  1. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第30篇]大致简述密钥协商中的BR安全定义
  2. 康宁玻璃ct值计算公式_【钦州】CT室铅板生产厂家
  3. scrapy ip地址 tcp time out_TCP的运作流程(一)——“三次握手”
  4. python汉字长度_行中字符串的长度(Python)
  5. 前台文件_欧木瑾怎么定制办公前台?
  6. 1555C. Coin Rows
  7. RT-Thread中堆和栈内存的分配
  8. MongoClient类参考文档
  9. oracle存储过程使用ftp,ASM存储FTP上传文件
  10. 防灾科技学院计算机组成原理,防灾科技学院计算机组成原理复习材料1