列表

详情


NC20708. Where are you

描述

小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

说明:


样例解释:


几种可能的方案如下:




可以证明,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

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 148ms, 内存消耗: 16348K, 提交时间: 2018-12-04 20:30:52

#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);
			if(x==y) continue;
			dfn[x]=dfn[y]=0;
			g[x].clear(),g[y].clear();
			unite(x,y);
		}
	}
	int num=0;for(int i=1;i<=m;i++) if(ans[i]) num++;
	printf("%d\n",num);
	return 0;
}

C++14(g++5.4) 解法, 执行用时: 154ms, 内存消耗: 12068K, 提交时间: 2020-08-05 11:53:13

#include<bits/stdc++.h>
using namespace std;

struct node
{
	int x,y,w;
}E[200005];
bool cmp(node a,node b)
{
	return a.w<b.w;
}
vector<int>R[200005];
int ans=0,V[200005],dfn[200005],low[200005],tot=0;
int find(int a)
{
	if(V[a]==a)return a;
	return V[a]=find(V[a]);
}
void tarjan(int x,int fa)
{
    int i,j,flag=1;
    dfn[x]=low[x]=++tot;
    for(i=0;i<R[x].size();i++)
    {
        j=R[x][i];
        if(j==fa&&flag){flag=0;continue;}
        if(!dfn[j])
        {
            tarjan(j,x);
			low[x]=min(low[x],low[j]);
            if(low[j]>dfn[x])ans++;
        }
        else low[x]=min(low[x],dfn[j]);
    }
}
int main()
{
    int i,j,k,a,b,n,m;
    scanf("%d%d%d",&n,&m,&i);
    for(i=1;i<=n;i++)V[i]=i;
    for(i=0;i<m;i++)scanf("%d%d%d",&E[i].x,&E[i].y,&E[i].w);
	sort(E,E+m,cmp);
	for(i=0;i<m;i=j)
	{
		for(j=i+1;j<m&&E[i].w==E[j].w;j++);
		for(k=i;k<j;k++)
		{
			a=find(E[k].x),b=find(E[k].y);
			if(a!=b)R[a].push_back(b),R[b].push_back(a);
		}
		for(k=i;k<j;k++)
		{
			a=find(E[k].x),b=find(E[k].y);
			if(a!=b&&!dfn[a])tarjan(a,0);
		}
		for(k=i;k<j;k++)
		{
			a=find(E[k].x),b=find(E[k].y);
			R[a].clear(),R[b].clear();
			dfn[a]=dfn[b]=0;
			if(a!=b)V[a]=b;
		}
	}
	printf("%d\n",ans);
    return 0;
}

上一题