牛客练习赛32-D-MST+tarjin割边

链接:https://ac.nowcoder.com/acm/contest/272/D
来源:牛客网

题目描述

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

输入描述:

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

输出描述:

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

    
牛客练习赛32-D-MST+tarjin割边
连通图没怎么学过很伤= =
  看了很久这个题解大概明白了思路,按照kruskal的方法,按照相同的w分类来讨论哪些边是必不可少的,如果在当前的图中e是割边,
就说明付出w的代价使得图的连通性增强了1,显然这条边必不可少。如果不是割边,无论他会不会使得连通性增加我们都不必考虑。
  譬如w1<w2<w3在进行w2轮次时,如果两个端点已经联通这条边显然没必要,如果未联通且是割边,那他就是必不可少的边。因为按照
贪心的思想必须这么做。
 #include<bits/stdc++.h>
using namespace std;
const int maxn=;
int root,sum=,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*];
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==(^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]=;
}
}
}
int main(){
int i,j,n,m,p,u,v,w;
scanf("%d%d%*d",&n,&m);
tot=;
memset(first,-,sizeof(first));
for(i=;i<=n;++i)f[i]=i;
for(i=;i<m;++i){
scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].w);
}
sort(E,E+m);
for(i=;i<m;++i){
j=i;
while(j+<m&&E[j+].w==E[i].w)j++;
tot=;
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,-);
}
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]=-;
dfn[fu]=dfn[fv]=;
f[fu]=fv;
}
i=j;
}
int h=;
for(i=;i<m;++i)h+=ans[i];
cout<<h<<endl;
return ;
}

 
上一篇:The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.


下一篇:fireBug引入JQuery,方便书写jq调试代码