zoukankan      html  css  js  c++  java
  • [CF160D](Edges in MST)

    题意:给你一个无向带权图,求每一条边:

    1.在每个最小生成树中.

    2.在部分最小生成树中.

    3.不在任何一个最小生成树中.

    solution:

    建立并查集

    将每条边按边权从小到大排序:

    如果一条边的两端都在同一联通块中则该边为none

    但是any 怎么区分呢

    这就要用到割边的知识

    我们把每组权相等的边拿出来

    重新建图 (tips:保留原有的联通块(连通块以其祖先标记)

    tarjan跑割边,此时割边即为any

    否则是at least one

    code:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define N 200005
    using namespace std;
    struct zero{
      int nxt,to,id;
    }edge[N<<1];
    int head[N],tot=0;
    void add_edge(int a,int b,int c){
      edge[++tot]=(zero){head[a],b,c};
      head[a]=tot;
    }
    struct sett{
      int u,v,w,id;
    }lib[N];
    int n,m,f[N],ans[N];
    int dfn[N],idx=0;
    int tarjan(int x,int pre){
      int lowu=dfn[x]=++idx;
      for(int i=head[x];i!=-1;i=edge[i].nxt){
        int to=edge[i].to;
        if(!dfn[to]){
          int lowv=tarjan(to,i);
          if(lowv>=dfn[to])ans[edge[i].id]=1;
          lowu=min(lowu,lowv);
          }
        else if(dfn[to]<dfn[x]&&i!=(pre^1))lowu=min(lowu,dfn[to]);
        }
      return lowu;
      }
    bool cmp(sett a,sett b){return a.w<b.w;}
    int find(int k){return (f[k]==k)?k:f[k]=find(f[k]);}
    int main(){
      scanf("%d%d",&n,&m);
      for(int i=1;i<=m;i++){
        scanf("%d%d%d",&lib[i].u,&lib[i].v,&lib[i].w);
        lib[i].id=i;
        }
      sort(lib+1,lib+m+1,cmp);
      for(int i=1;i<=m;i++)f[i]=i;
      int last;
      for(int i=1;i<=m;i++){
        last=i;
        while(last<=m&&lib[last].w==lib[i].w)last++;last--;
        for(int r=i;r<=last;r++){
          lib[r].u=find(lib[r].u);
          lib[r].v=find(lib[r].v);
          if(lib[r].u==lib[r].v){
            ans[lib[r].id]=-1;
            continue;
            }
          dfn[lib[r].u]=dfn[lib[r].v]=0;
          head[lib[r].u]=head[lib[r].v]=-1;
          }
        idx=0;tot=-1;
        for(int r=i;r<=last;r++)
          if(lib[r].u!=lib[r].v)
            add_edge(lib[r].u,lib[r].v,lib[r].id),
            add_edge(lib[r].v,lib[r].u,lib[r].id);
        for(int r=i;r<=last;r++)
          if(!dfn[lib[r].u])tarjan(lib[r].u,-1);
        for(int r=i;r<=last;r++){f[find(lib[r].u)]=find(lib[r].v);}
          i=last;
        }
      for(int i=1;i<=m;i++){
        if(ans[i]==-1)puts("none");
        else if(ans[i]==1)puts("any");
        else puts("at least one");
        }
      }
  • 相关阅读:
    Java获取EXE文件图标的方法
    项目组:ouc海票票 第七周Scrum meeting会议记录
    NBear使用的注意点
    几个错误
    DataGrid列中如何去掉小数后的零
    自己看着视频的理解:设计模式之abstractfactory模式(2)
    SQL SERVER 与ACCESS、EXCEL之间的数据转换(转载)
    .NET 将文本转换成语音 (转)
    InstallShield 打包需要的几段脚本代码
    SQL2005性能分析一些细节功能你是否有用到? (转)
  • 原文地址:https://www.cnblogs.com/stepsys/p/10374997.html
Copyright © 2011-2022 走看看