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

 

你可能感兴趣的:(c)