CF160D

题意:给你一个图,判断每条边是否在最小生成树MST上,不在输出none,如果在所有MST上就输出any,在某些MST上输出at least one;

分析:首先必须知道在最小生成树上的边的权值一定是等于任意最小生成树上的某条边的权值;那么我们按边的权值排序,每次同时加入权值相等的边

如果加入这条边之后形成loop那么这条边肯定不是最小生成树上的边,因为在此次加边之前,图上边的权值肯定是小于此次加入的边的权值的,如果加入这条边之后形成环,那么肯定不是MST上的边;加完边之后,如果这条边是bridge,那么这条边肯定是any,因为这条边是连接两个连通块的最小唯一边,如果边在剩下的边肯定在某些MST上;

注意:每一个阶段加完边之后要,要求出此阶段的联通情况,然后一个联通快缩点,然后在继续,这样每条边最多被经历一次,时间是O(m);

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<vector>
  8 #include<set>
  9 #include<stack>
 10 using namespace std;
 11 const int N = 100000+10;
 12 struct node{
 13     int v,id;
 14     node(){}
 15     node(int v,int id):v(v),id(id){}
 16 };
 17 vector<node> G[N];
 18 int pre[N], low[N], eccno[N], dfs_clock, ecc_cnt;
 19 stack<int> SK;
 20 int an[N];
 21 int num;
 22 int vis[N];
 23 void dfs(int u,int fa) {
 24     pre[u] = low[u] = ++dfs_clock;
 25     int sz = G[u].size();
 26     bool first = true;
 27     for (int i = 0 ;i < sz; i++) {
 28         int v = G[u][i].v;
 29         if (v == fa && first)  {
 30                 first = false;
 31             continue;
 32         }
 33         if (pre[v] == 0) {
 34             dfs(v,u);
 35             low[u] = min(low[u], low[v]);
 36             if (low[v] > pre[u]) an[G[u][i].id] = 2;
 37         }else {
 38             low[u] = min(low[u],pre[v]);
 39         }
 40     }
 41 
 42 }
 43 
 44 int n,m;
 45 struct edge{
 46     int u,v,w,id;
 47     edge(){}
 48     edge(int u,int v,int w, int id):u(u),v(v),w(w),id(id){}
 49     bool operator < (const edge &p) const{
 50         return w < p.w;
 51     }
 52 };
 53 vector<edge> Eg;
 54 int p[N];
 55 int find(int x) {
 56     return p[x] == x ? x : p[x] = find(p[x]);
 57 }
 58 int mark[N];
 59 void build_graph(){
 60      sort(Eg.begin(),Eg.end());
 61      for (int i = 0; i <= n; i++) p[i] = i;
 62      memset(mark,0,sizeof(mark));
 63      for (int i = 0; i < Eg.size(); i++) {
 64         int j = i;
 65         for (; j < Eg.size() && Eg[j].w == Eg[j+1].w; j++);
 66           for (int k = i; k <= j; k++) {
 67             int u = Eg[k].u, v = Eg[k].v, w = Eg[k].w;
 68             int x = find(u), y = find(v);
 69             if (x != y) {
 70                 G[x].push_back(node(y,Eg[k].id));
 71                 G[y].push_back(node(x,Eg[k].id));
 72                 an[Eg[k].id] = 1;
 73                 pre[x] = pre[y] = 0;
 74                 mark[k] = x;
 75             }
 76         }
 77         dfs_clock = 0;
 78         for (int k = i; k <= j; k++) {
 79             if (mark[k] && pre[mark[k]] == 0) dfs(mark[k],-1);
 80         }
 81         for (int k = i; k <= j; k++) {
 82             int u = Eg[k].u, v = Eg[k].v, w = Eg[k].w;
 83             int x = find(u), y = find(v);
 84             if (x != y) {
 85                 p[x] = y;
 86                 G[x].clear(); G[y].clear();
 87             }
 88         }
 89         i = j;
 90      }
 91 
 92 }
 93 void solve(){
 94     memset(an,0,sizeof(an));
 95     build_graph();
 96     for (int i = 0; i < m; i++) {
 97         if (an[i] == 0) printf("none\n");
 98         else if (an[i] == 1) printf("at least one\n");
 99         else if (an[i] == 2) printf("any\n");
100     }
101 }
102 int main(){
103     while (~scanf("%d%d",&n,&m)) {
104         Eg.clear();
105         for (int i = 0; i < m; i++) {
106             int u,v,w;
107             scanf("%d%d%d",&u,&v,&w);
108             Eg.push_back(edge(u,v,w,i));
109         }
110         solve();
111     }
112 
113     return 0;
114 }
View Code

 

转载于:https://www.cnblogs.com/Rlemon/p/3278876.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值