D. Tenzing and His Animal Friends

지문이 진짜 미친놈인데, $m$개의 조건이 도대체 뭘 의미하는건지 한참 생각했다.

노는 시간 중 $u, v$가 정확히 한 명만 있는 노는 시간이 $y$ 이하여야 한다는 조건이다.

이 조건을 이용해 이걸 최단거리 문제로 환원할 수 있다.

$1\ 3 \ 5$ 라는 조건이 있다고 하자.

그럼 $1$은 항상 껴있으므로 $1???\dots$으로 시작을 하고 $3$ 은 5초 뒤에 들어갈 수 있다는 것이다.

대략 정답은 다음과 같이 구성될 수 있겠다.

1?0??... 5
1?1??... ?

그래서 일단 $1$에서 시작하는 최단거리를 모두 구해서 $n$ 까지 최단거리를 구하자.

$n$까지 도달할 수 없다면 $1 \sim n-1$ 을 모두 $1$ 로 처리해버린다음에 무한히 진행할 수 있어서 정답은 inf 이다.

그렇지 않다면 정답은 $T=d_n$ 이다.

정답을 구성하는 방법은 최단거리를 기준으로 오름차순 정렬하고 현재 보고있는 인덱스는 뒤에 모두 계속 $1$로 바꿔주는 것이다.

같은 dist를 가진것들은 한 번에 처리해주면 된다.

바로 이전 값과의 $d$ 차이를 기록하고, 이전 값의 $t$ 값을 이 차이로 넣어준다.

그다음 마지막에는 정답 하나를 지운다. $n$이 $1$이 들어가는 행이 하나 생기기 때문이다.

const int inf = 2e18;  
  
void solve() {  
   int n, m;  
   cin >> n >> m;  
   vi dist(n, inf);  
   vector<vector<pi>> edges(n);  
   for (int i = 0; i < m; i++) {  
      int u, v, y;  
      cin >> u >> v >> y, u--, v--;  
      edges[u].pb({v, y});  
      edges[v].pb({u, y});  
   }  
   dist[0] = 0;  
   queue<int> q;  
   q.push(0);  
   while (sz(q)) {  
      int cur = q.front();  
      q.pop();  
      for (auto &[to, w]: edges[cur]) {  
         if (dist[to] > w + dist[cur]) {  
            dist[to] = w + dist[cur];  
            q.push(to);  
         }  
      }  
   }  
   if (dist[n - 1] == inf) {  
      cout << "inf";  
      return;  
   }  
  
   vector<pair<string, int>> ans;  
   vi idx(n);  
   iota(all(idx), 0);  
   for (int i = 0; i < n; i++) mina(dist[i], dist[n - 1]);  
   sort(all(idx), [&](int i, int j) { return dist[i] != dist[j] ? dist[i] < dist[j] : i < j; });  
   vi in(n);  
   debug(dist[n - 1]);  
   cout << dist[n - 1] << ' ';  
   for (int _i = 0, last = 0; _i < n;) {  
      int i = idx[_i];  
      int _j = _i;  
      while (_j < n && dist[idx[_j]] == dist[i]) {  
         in[idx[_j]] = 1;  
         _j++;  
      }  
  
      int dt = dist[i] - last;  
  
      if (_i) ans.back().se = dt;  
      ans.pb({string(n, '0'), 0});  
  
      for (int k = 0; k < n; k++) if (in[k]) ans.back().fi[k] = '1';  
  
      last = dist[i];  
      _i = _j;  
   }  
   ans.pop_back();  
   cout << sz(ans) << endl;  
   for (auto &[a, b]: ans) cout << a << ' ' << b << endl;  
}

Comments