最小生成树
给你一个带权连通的无向图,对于最小生成树,大家都很熟悉了,我这里就不定义了。对于任意一个连通图,显然存在最小生成树,但是在通常情况下,一个图的最小生成树是不唯一的。你的任务就是:对于给你的图,来确定该图的每一条边是否在任意一棵最小生成树中,或者是至少在某一棵最小生成树中,或者是不在最小生成树中。
【输入格式】
输入的第一行含有两个整数n和m(2<=n<=1e5,n-1<=m<=min(e=1e5,n*(n-1)/2)),分别表示顶点数和边数。
接下来m行,描述这边的信息,格式为“ai bi wi”(1<=ai,bi<=n,1<=wi<=1e6,ai!=bi),ai和bi为第i条边的两个顶点,wi为这条边的权值。这图保证是连通的且不含有重边。
【输出格式】
输出m行信息,如果第i条边包含在任何一棵最小生成树中,那么输出“any”;如果第i条边至少包含在某一棵最小生成树中,那么输出“at least one”;如果第i条边不在任何一棵最小生成树中,那么输出“none”。按输入边的顺序给出答案。
【输入样例1】
4 5
1 2 101
1 3 100
2 3 2
2 4 2
3 4 1
【输出样例1】
none
any
at least one
at least one
any
【输出样例2】
3 3
1 2 1
2 3 1
1 3 2
【输出样例2】
at least one
at least one
at least one
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 100003
using namespace std;
int n,m;
int point[N],next[N],v[N],c[N],tot,fa[N],pd[N];
int low[N],dfsn[N],st[N],top,q[N],size,sz,cnt;
int par[N],ins[N];
struct data
{
int x,y,z;
int num;
}a[N];
void add(int x,int y,int z)
{
tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;
tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; c[tot]=z;
}
int cmp(data a,data b)
{
return a.z<b.z;
}
int find(int x)
{
if (fa[x]==x) return x;
fa[x]=find(fa[x]);
return fa[x];
}
void tarjan(int x)
{
ins[x]=1;
low[x]=dfsn[x]=++sz;
for (int i=point[x];i;i=next[i])
if (!ins[v[i]])
{
par[v[i]]=c[i];
tarjan(v[i]);
low[x]=min(low[x],low[v[i]]);
}
else if (c[i]!=par[x]) low[x]=min(low[x],dfsn[v[i]]);
if (low[x]==dfsn[x]&&par[x]) pd[par[x]]++;
}
int main()
{
freopen("mst.in","r",stdin);
freopen("mst.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z),a[i].num=i;
sort(a+1,a+m+1,cmp);
for (int i=1;i<=n;i++)
fa[i]=i;
int i=1; int num=0;
while (i<=m)
{
if (a[i].z>a[i-1].z)
{
int j=i;
while (a[j].z==a[i].z&&j<=m)
j++;
j--; tot=0; size=0; top=0; sz=0; cnt=0;
for (int k=i;k<=j;k++)
{
int r1=find(a[k].x); int r2=find(a[k].y);
if (r1!=r2)
{
pd[a[k].num]=1;
point[r1]=0; point[r2]=0; dfsn[r1]=0; dfsn[r2]=0;
low[r1]=0; low[r2]=0; ins[r1]=0; ins[r2]=0;
par[r1]=0; par[r2]=0;
q[++size]=r1; q[++size]=r2;
}
}
for (int k=i;k<=j;k++)
if (pd[a[k].num])
{
int r1=find(a[k].x); int r2=find(a[k].y);
add(r1,r2,a[k].num);
//cout<<r1<<" "<<r2<<endl;
}
for (int k=1;k<=size;k++)
if (!dfsn[q[k]]) tarjan(q[k]);
for (int k=i;k<=j;k++)
{
int r1=find(a[k].x);
int r2=find(a[k].y);
if (r1!=r2)
{
num++;
fa[r2]=r1;
}
}
if (num==n-1) break;
i=j+1;
}
}
for (int i=1;i<=m;i++)
if (!pd[i]) printf("none\n");
else if (pd[i]==1) printf("at least one\n");
else printf("any\n");
}