Problem p00929 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
struct node {
  int id, u, v, cost, next;
  bool vis;
} edge[100010], arr[50010];
int T, t, n, m;
int p[50010], Head[510], tot, tot2, tot3, tot4, ans1, ans2;
int vis[510], U[510];
int stack[510], DFN[510], Low[510], Belong[510];
bool instack[510];
int top, cnt, scnt;
bool cmp(node a, node b) { return a.cost < b.cost; }
int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }
void _add(int u) {
  if (vis[u] != t) {
    vis[u] = t;
    U[++U[0]] = u;
  }
}
void add(int u, int v, int cost) {
  // printf("%d %d %d\\n",u,v,cost);
  edge[tot2].u = u;
  edge[tot2].v = v;
  edge[tot2].next = Head[u];
  edge[tot2].vis = 0;
  Head[u] = tot2++;
}
void Tarjan(int u) {
  // printf("Tarjan %d\\n",u);
  int i, j, k, v;
  DFN[u] = Low[u] = ++tot4;
  instack[u] = 1;
  stack[top++] = u;
  for (i = Head[u]; i >= tot; i = edge[i].next) {
    v = edge[i].v;
    if (edge[i].vis == 1)
      continue;
    edge[i].vis = edge[i ^ 1].vis = 1;
    if (DFN[v] <= tot3) {
      Tarjan(v);
      Low[u] = min(Low[u], Low[v]);
    } else if (instack[v])
      Low[u] = min(Low[u], DFN[v]);
  }
  if (DFN[u] == Low[u]) {
    scnt++;
    do {
      v = stack[--top];
      instack[v] = 0;
      Belong[v] = scnt;
    } while (u != v);
  }
}
int main() {
  int i, j, k, l, r, u, v;
  scanf("%d%d", &n, &m);
  for (i = 1; i <= m; i++) {
    scanf("%d%d%d", &arr[i].u, &arr[i].v, &arr[i].cost);
    arr[i].id = i;
  }
  for (i = 1; i <= n; i++)
    p[i] = i;
  memset(Head, -1, sizeof(Head));
  sort(arr + 1, arr + 1 + m, cmp);
  l = r = 1;
  while (r <= m) {
    while (r < m && arr[r + 1].cost == arr[r].cost)
      r++;
    tot = tot2;
    t++;
    U[0] = 0;
    for (i = l; i <= r; i++) {
      u = find(arr[i].u);
      v = find(arr[i].v);
      if (u == v)
        continue;
      _add(v);
      _add(u);
      add(u, v, arr[i].cost);
      add(v, u, arr[i].cost);
    }
    tot3 = tot4;
    top = cnt = scnt = 0;
    for (i = 1; i <= U[0]; i++)
      if (DFN[U[i]] <= tot3)
        Tarjan(U[i]);
    // for(i=1;i<=U[0];i++)
    //    printf("Belong %d\\n",Belong[U[i]]);
    for (i = l; i <= r; i++)
      if (Belong[find(arr[i].u)] != Belong[find(arr[i].v)]) {
        ans1++;
        ans2 += arr[i].cost;
      }

    for (i = l; i <= r; i++) {
      u = find(arr[i].u);
      v = find(arr[i].v);
      if (u == v)
        continue;
      p[v] = u;
    }
    l = r = r + 1;
  }
  printf("%d %d\\n", ans1, ans2);
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;

const int maxn = 500 + 10;
const int maxm = 50000 + 10;
const int INF = 0x3f3f3f3f;

struct Edge {
  int u, v, w, next;
  int tag, p;
  Edge(int u = 0, int v = 0, int w = 0) : u(u), v(v), w(w) {
    tag = 0;
    p = 0;
    next = 0;
  }
  friend bool operator<(const Edge &e1, const Edge &e2) { return e1.w < e2.w; }
} edges[maxm << 1];

int head[maxn], tot;
int n, m;

int p[maxn], vis[maxm << 1], parent[maxn], sum;

void addEdge(int i) {
  int u = edges[i].u;
  edges[i].next = head[u];
  head[u] = i;
}

void init() {
  tot = 0;
  memset(head, -1, sizeof(head));

  for (int i = 1; i <= n; i++)
    p[i] = i;
  memset(vis, 0, sizeof(vis));
  memset(parent, 0, sizeof(parent));
}

// void print_tree(int cur){
//	for(int i=1;i<=n;i++){
//		if(parent[i]!=0) printf("%d -> %d\\n",parent[i],i);
//	}
// }

int vis1[maxn];
void dfs(int cur) {
  int po = head[cur];
  while (po != -1) {
    Edge &e = edges[po];
    if (!vis1[e.v]) {
      vis1[e.v] = 1;
      e.p = cur;
      parent[e.v] = cur;
      dfs(e.v);
    }
    po = e.next;
  }
}

void build_tree() {
  memset(vis1, 0, sizeof(vis1));
  vis1[1] = 1;
  dfs(1);
  //	printf("tree:\\n");
  //	print_tree(1);
  //	printf("\\nendtree\\n");
}

int Findset(int x) { return p[x] == x ? x : Findset(p[x]); }

void kruskal() {
  sort(edges, edges + tot);
  sum = 0;
  for (int i = 0; i < tot; i += 2) {
    int u = edges[i].u, v = edges[i].v;
    int pu = Findset(u), pv = Findset(v);
    if (pu != pv) {
      sum += edges[i].w;
      p[pv] = pu;
      addEdge(i);
      addEdge(i ^ 1);
      vis[i] = vis[i ^ 1] = 1;
    }
  }
  //	printf("sum:%d\\n",sum);
}

int FindCom(int x, int y) {
  memset(vis1, 0, sizeof(vis1));
  //	vis1[x]=vis1[y]=1;
  while (x != 1) {
    vis1[x] = 1;
    x = parent[x];
  };
  vis1[x] = 1;
  //	printf("vis1[%d]:%d\\n",y,vis1[y]);
  while (!vis1[y]) {
    vis1[y] = 1;
    y = parent[y];
  };
  //	printf("x:%d,y:%d\\n",x,y);
  return y;
}
int ans1, ans2;

void dfs1(int cur, int w) {
  int po = head[cur];
  while (po != -1) {
    Edge &e = edges[po];
    if (vis1[e.v] && parent[e.v] == cur) {
      if (e.w == w) {
        //				printf("(%d,%d)\\n",e.u,e.v);
        e.tag = 1;
      }
      dfs1(e.v, w);
      //			break;
    }
    po = e.next;
  }
}
void dfs2(int cur) {
  int po = head[cur];
  while (po != -1) {
    Edge &e = edges[po];
    if (parent[e.v] == cur) {
      if (e.tag) {
        ans1 -= e.w;
        ans2--;
      }
      dfs2(e.v);
    }
    po = e.next;
  }
}
void solve() {
  //	printf("in solve!\\n");
  //	memset(vis,0,sizeof(vis));
  ans1 = sum, ans2 = n - 1;
  for (int i = 0; i < tot; i += 2) {
    if (vis[i] == 0) {
      //			printf("(%d,%d)\\n",edges[i].u,edges[i].v);
      Edge &e = edges[i];
      int com = FindCom(e.u, e.v);
      //			printf("com:%d\\n",com);
      //			printf("before dfs1\\n");
      dfs1(com, e.w);
      //			printf("after dfs1!\\n");
    }
  }
  //	printf("before dfs2!\\n");
  dfs2(1);
  printf("%d %d\\n", ans2, ans1);
}

int main() {
  while (scanf("%d%d", &n, &m) == 2 && n) {
    init();
    for (int i = 1; i <= m; i++) {
      int u, v, w;
      scanf("%d%d%d", &u, &v, &w);
      edges[tot++] = Edge(u, v, w);
      edges[tot++] = Edge(v, u, w);
    }
    kruskal();
    build_tree();
    solve();
  }
  return 0;
}