zoukankan      html  css  js  c++  java
  • HYSBZ

    题目传送门

    题解:首先对于给定的图,需要找到那些从1好点出发然后到x号点的最短路, 如果有多条最短路就要找到字典序最小的路,这样扣完这些边之后就会有一棵树。然后再就是很普通的点分治了。

    对于扣边这个问题, 我们先跑一遍最短路,这样就可以得到1号点到其他的点的距离。

    然后在跑一遍dfs, 我们在跑dfs找路的时候, 可以通过 d[u] + ct[i] == d[v] 来判断是不是最短路是否可以走这条边, 然后我们再从所有可能边中的最小编号出发,这样我们就能保证字典序最小了。

    代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
      4 #define LL long long
      5 #define ULL unsigned LL
      6 #define fi first
      7 #define se second
      8 #define pb push_back
      9 #define lson l,m,rt<<1
     10 #define rson m+1,r,rt<<1|1
     11 #define lch(x) tr[x].son[0]
     12 #define rch(x) tr[x].son[1]
     13 #define max3(a,b,c) max(a,max(b,c))
     14 #define min3(a,b,c) min(a,min(b,c))
     15 typedef pair<int,int> pll;
     16 const int inf = 0x3f3f3f3f;
     17 const LL INF = 0x3f3f3f3f3f3f3f3f;
     18 const LL mod =  (int)1e9+7;
     19 const int N = 3e4 + 100;
     20 vector<pll> vc[N];
     21 int d[N];
     22 void dij(){
     23     memset(d, inf, sizeof(d));
     24     priority_queue<pll, vector<pll>, greater<pll> > q;
     25     d[1] = 0;
     26     q.push(pll(0,1));
     27     int x, dd, v, ct;
     28     while(!q.empty()){
     29         x = q.top().se, dd = q.top().fi;
     30         q.pop();
     31         if(dd != d[x]) continue;
     32         for(int i = 0; i < vc[x].size(); ++i){
     33             v = vc[x][i].fi , ct = vc[x][i].se;
     34             if(d[v] > d[x] + ct){
     35                 d[v] = d[x] + ct;
     36                 q.push(pll(d[v], v));
     37             }
     38         }
     39     }
     40     return;
     41 }
     42 int vis[N];
     43 int head[N], to[N<<2], val[N<<2], nt[N<<2], tot = 0;
     44 void add(int u, int v, int ct){
     45     to[tot] = v;
     46     val[tot] = ct;
     47     nt[tot] = head[u];
     48     head[u] = tot++;
     49     return ;
     50 }
     51 void dfs(int u){
     52     vis[u] = 1;
     53     int v, dd;
     54     for(int i = 0; i < vc[u].size(); i++){
     55         v = vc[u][i].fi, dd = vc[u][i].se;
     56         if(vis[v] || d[v] != d[u] + dd) continue;
     57         add(u, v, dd);
     58         add(v, u, dd);
     59         dfs(v);
     60     }
     61     return ;
     62 }
     63 int sz[N];
     64 int rt, minval;
     65 int n, m, k;
     66 void get_rt(int o, int u, int num){
     67     sz[u] = 1;
     68     int v;
     69     int maxval = 0;
     70     for(int i = head[u]; ~i; i = nt[i]){
     71         v = to[i];
     72         if(v == o || vis[v]) continue;
     73         get_rt(u, v, num);
     74         sz[u] += sz[v];
     75         maxval = max(maxval, sz[v]);
     76     }
     77     if(o) maxval = max(maxval, num - sz[u]);
     78     if(maxval < minval){
     79         minval = maxval;
     80         rt = u;
     81     }
     82 }
     83 int fans = 0, fcnt = 0;
     84 int cnt[N], dis[N];
     85 void Update(int vval, int num){
     86     if(fans == vval) fcnt += num;
     87     else if(fans < vval) fans = vval, fcnt = num;
     88     return ;
     89 }
     90 void Dfs(int o, int u, int w, int num){
     91     sz[u] = 1;
     92     if(num == k-1)
     93         Update(w, 1);
     94     if(k >= num && dis[k-num]){
     95         Update(w+dis[k-num], cnt[k-num]);
     96     }
     97     for(int i = head[u]; ~i; i = nt[i]){
     98         int v = to[i];
     99         if(v == o || vis[v]) continue;
    100         Dfs(u, v,w+val[i], num+1);
    101         sz[u] += sz[v];
    102     }
    103     return ;
    104 }
    105 void Change(int o, int u, int w, int num, int op){
    106     if(num >= k) return ;
    107     if(op == 1) {
    108         if(dis[num+1] < w) dis[num+1] = w, cnt[num+1] = 1;
    109         else if(dis[num+1] == w) cnt[num+1]++;
    110     }
    111     else dis[num+1] = cnt[num+1] = 0;
    112     for(int i = head[u]; ~i; i = nt[i]){
    113         int v = to[i];
    114         if(v == o || vis[v]) continue;
    115         Change(u, v, w+val[i], num+1, op);
    116     }
    117     return ;
    118 }
    119 void solve(int x, int num){
    120     if(num <= 1) return ;
    121     minval = inf;
    122     get_rt(0, x, num);
    123     vis[rt] = 1;
    124     int v;
    125     for(int i = head[rt]; ~i; i = nt[i]){
    126         v = to[i];
    127         if(vis[v]) continue;
    128         Dfs(0, v, val[i], 1);
    129         Change(0, v, val[i], 1, 1);
    130     }
    131     for(int i = head[rt]; ~i; i = nt[i]){
    132         v = to[i];
    133         if(vis[v]) continue;
    134         Change(0, v, val[i], 1, 0);
    135     }
    136     for(int i = head[rt]; ~i; i = nt[i]){
    137         v = to[i];
    138         if(vis[v]) continue;
    139         solve(v, sz[v]);
    140     }
    141     return ;
    142 }
    143 int main(){
    144     int u, v, w;
    145     memset(head, -1, sizeof(head));
    146     scanf("%d%d%d", &n, &m, &k);
    147     for(int i = 1; i <= m; i++){
    148         scanf("%d%d%d", &u, &v, &w);
    149         vc[u].pb(pll(v,w));
    150         vc[v].pb(pll(u,w));
    151     }
    152     dij();
    153     dfs(1);
    154     memset(vis, 0, sizeof(vis));
    155     solve(1, n);
    156     printf("%d %d", fans, fcnt);
    157     return 0;
    158 }
    View Code
  • 相关阅读:
    join命令
    参与者模式
    字符串中的第一个唯一字符
    Git与SVN对比
    惰性模式
    .NET Conf 2020
    使用Github部署Azure应用服务
    Azure Terraform(一)入门简介
    打日志还能打出个线上Bug_ 太难了。。。
    让API并行调用变得如丝般顺滑的绝招
  • 原文地址:https://www.cnblogs.com/MingSD/p/9890622.html
Copyright © 2011-2022 走看看