最小生成树 (tarjan 求桥)

来源:互联网 发布:2016年济南市酒驾数据 编辑:程序博客网 时间:2024/04/28 17:43

最小生成树
给你一个带权连通的无向图,对于最小生成树,大家都很熟悉了,我这里就不定义了。对于任意一个连通图,显然存在最小生成树,但是在通常情况下,一个图的最小生成树是不唯一的。你的任务就是:对于给你的图,来确定该图的每一条边是否在任意一棵最小生成树中,或者是至少在某一棵最小生成树中,或者是不在最小生成树中。
【输入格式】
输入的第一行含有两个整数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 100003using 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");}


0 0
原创粉丝点击