codeforces 160D Edges in MST

来源:互联网 发布:java哪个老师出名 编辑:程序博客网 时间:2024/05/16 14:55

给你一幅图,对于图中的每一条边,判断

1、存在于任何一颗最小生成树中 any

2、至少存在于某一颗最小生成树中  at least one

3、不存在任何一棵最小生成树中 none

看见就想一做的图论题

思路:至少存在于某一颗最小生成树中 这种情况只可能存在于相同权值的边中,所以每次对于同一权值的边一起处理,再用 最小生成树中克鲁斯卡尔的方法来搞

利用并查集:如果某时刻一条边的两个端点在同一集合,如果添加这一条边,就会形成一个环,而环中其他的边都是在上一轮已经添加进去了的(权值都比当前边小)

所以当前边是none(一开始初始化为none),如果不在同一集合,标记为at least one,对两个集合建边,建完边后对所建边集求双连通分量,把是桥的边标记为any。最后对不在同一集合上的点进行合并,把刚才建的边删掉。

View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100010;
const int M = 100010;
char ANS[][15]={"none","any","at least one"};
int min(int a,int b){
return a>b?b:a;
}
struct EDGE{
int st,to,next,id,ans,tag,w;
}edge[2*M],data[M];
int cmp(EDGE a,EDGE b){
return a.w<b.w;
}
int cmp1(EDGE a,EDGE b){
return a.id<b.id;
}
int n,m,tot,tdfn;
int head[N],vis[N],low[N],dfn[N],fa[N],com[M];
void add(int a,int b,int edgeid)
{
int j,flag=0;
edge[tot].to=b;
edge[tot].id=edgeid;
edge[tot].next=head[a];
head[a]=tot++;
}
void dfs(int u,int fa,int depth){
int i,v;low[u]=dfn[u]=depth;vis[u]=1;
for(i=head[u];i!=-1;i=edge[i].next){
v=edge[i].to;
if(vis[v]==1&&edge[i].id!=fa) low[u]=min(low[u],dfn[v]);
else if(!vis[v]){
dfs(v,edge[i].id,depth+1);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]) data[edge[i].id].ans=1;
}
}
vis[u]=2;
}
int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]);}
int main()
{
int i,j,k,a,b,w,x,y;
scanf("%d%d",&n,&m);
for(i=0;i<=n;i++)fa[i]=i;
for(i=1;i<=m;i++){
scanf("%d%d%d",&data[i].st,&data[i].to,&data[i].w);
data[i].ans=0;
data[i].id=i;
}
sort(data+1,data+m+1,cmp);
memset(head,-1,sizeof(head));
tot=0;
for(i=1;i<=m;)
{
int s=i;
for(j=i;data[j].w==data[i].w&&j<=m;j++);
i=j;
for(j=s;j<i;j++)
{
x=find(data[j].st);
y=find(data[j].to);
if(x==y) continue;
data[j].ans=2;
add(x,y,j);
add(y,x,j);
com[j]=x;
}
for(j=s;j<i;j++)
{
if(com[j]&&!vis[com[j]])
{
dfs(com[j],0,1);
}
}
for(j=s;j<i;j++)
{
x=find(data[j].st);
y=find(data[j].to);
if(x!=y)
{
vis[x]=vis[y]=0;
head[x]=head[y]=-1;
fa[x]=y;
}
}
tot=0;
}
sort(data+1,data+1+m,cmp1);
for(i=1;i<=m;i++)
{
printf("%s\n",ANS[data[i].ans]);
}
return 0;
}



原创粉丝点击