• Codeforces Round #260 (Div. 1)C. Civilization 并查集+树的直径


    题目链接:

    http://codeforces.com/problemset/problem/455/C

    题意:

    n个点,m条边的森林,q次操作。每次操作:1、询问x所在树的直径 2、合并x和y所在的树,使得合并后的直径最小
    (1 ≤ n ≤ 3e5; 0 ≤ m < n1 ≤ q ≤ 3e5)

    思路:

    一棵树的最长路径是树的直径,可以用并查集维护每棵树的直径,然后合并两棵树的时候要使新树的最长路径最小,

    考虑怎么使合并的时候两颗树的直径最小,加的边一定连接两棵树的直径的中点,用并查集维护,合并后的树的直径是

    max(ans[p1],max(ans[p2],(ans[p1]+1)/2+(ans[p2]+1)/2+1));

    我找树的直径是用spfa,多棵树的时候,对全部的点都初始化了,TLE。 所以把每颗树单独拿出来,计算答案。

    代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 #define MS(a) memset(a,0,sizeof(a))
      5 #define MP make_pair
      6 #define PB push_back
      7 const int INF = 0x3f3f3f3f;
      8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
      9 inline ll read(){
     10     ll x=0,f=1;char ch=getchar();
     11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     13     return x*f;
     14 }
     15 //////////////////////////////////////////////////////////////////////////
     16 const int maxn = 3e5+10;
     17 
     18 int n,m,Q;
     19 int ans[maxn],fa[maxn];
     20 int inq[maxn],d[maxn];
     21 vector<int> g[maxn],gg[maxn];
     22 queue<int> q;
     23 int vis[maxn];
     24 
     25 int find(int x){
     26     return fa[x]==x ? x : fa[x]=find(fa[x]);
     27 }
     28 
     29 int main(){
     30     MS(ans);
     31     cin >> n >> m >> Q;
     32     for(int i=0; i<=n; i++) g[i].clear(),gg[i].clear();
     33     for(int i=0; i<=n; i++) fa[i] = i, vis[i]=0;
     34     for(int i=0; i<m; i++){
     35         int u,v; scanf("%d%d",&u,&v);
     36         g[u].push_back(v);
     37         g[v].push_back(u);
     38         int p1 = find(u), p2 = find(v);
     39         if(p1 == p2) continue;
     40         else fa[p1] = p2;
     41     }
     42     for(int i=1; i<=n; i++){
     43         int p = find(i);
     44         gg[p].push_back(i);
     45     }
     46     for(int u=1; u<=n; u++){
     47         if(fa[u]!=u) continue;
     48         inq[u] = 0, d[u] = INF;
     49         for(int i=0; i<(int)gg[u].size(); i++) {
     50             int v = gg[u][i];
     51             inq[v]=0; d[v] = INF;
     52         }
     53         q.push(u);
     54         inq[u]=1; d[u]=0;
     55         while(!q.empty()){
     56             int now = q.front(); q.pop();
     57             for(int i=0; i<(int)g[now].size(); i++){
     58                 int v = g[now][i];
     59                 if(d[v] > d[now]+1){
     60                     d[v] = d[now]+1;
     61                     if(inq[v]) continue;
     62                     inq[v] = 1;
     63                     q.push(v);
     64                 }
     65             }
     66         }
     67         int tmp = d[u], k;
     68         for(int i=0; i<(int)gg[u].size(); i++){
     69             int v = gg[u][i];
     70             if(d[v]==INF) continue;
     71             if(tmp < d[v]) tmp=d[v], k = v;
     72         }
     73 
     74         inq[u] = 0, d[u] = INF;
     75         for(int i=0; i<(int)gg[u].size(); i++) {
     76             int v = gg[u][i];
     77             inq[v]=0; d[v] = INF;
     78         }
     79         q.push(k);
     80         inq[k]=1; d[k]=0;
     81         while(!q.empty()){
     82             int now = q.front(); q.pop();
     83             for(int i=0; i<(int)g[now].size(); i++){
     84                 int v = g[now][i];
     85                 if(d[v] > d[now]+1){
     86                     d[v] = d[now]+1;
     87                     if(inq[v]) continue;
     88                     inq[v] = 1;
     89                     q.push(v);
     90                 }
     91             }
     92         }
     93 
     94         tmp = d[k];
     95         if(d[u]!=INF) tmp = max(tmp,d[u]);
     96         for(int i=0; i<(int)gg[u].size(); i++){
     97             int v = gg[u][i];
     98             if(d[v]==INF) continue;
     99             tmp = max(tmp,d[v]);
    100         }
    101         ans[u] = tmp;
    102 //        cout << u << " " << tmp << endl;
    103     }
    104 
    105     for(int i=0; i<Q; i++){
    106         int op = read();
    107         if(op == 1){
    108             int x = read();
    109             printf("%d
    ",ans[find(x)]);
    110         }else{
    111             int x,y; scanf("%d%d",&x,&y);
    112             int p1 = find(x), p2 = find(y);
    113 //            cout << p1 << " " << p2 << "  ==
    ";
    114             if(p1 != p2){
    115                 fa[p1] = p2;
    116 //                cout << ans[p1] << " " << ans[p2] << " **
    ";
    117                 ans[p2] = max(ans[p1],max(ans[p2],(ans[p1]+1)/2+(ans[p2]+1)/2+1));
    118             }
    119         }
    120     }
    121 
    122 
    123     return 0;
    124 }
  • 相关阅读:
    小程序导航栏文字动态修改
    小程序之页面跳转传递参数问题
    怎样像gitHub上上传文件
    js实现数组去重
    Promise 解决同步请求问题
    input 实现一次性上传文件
    layui中load具体用法
    echarts点击柱状图时触发点击事件
    js求100以内的素数
    js怎样判断一个数是质数
  • 原文地址:https://www.cnblogs.com/yxg123123/p/6898443.html
Copyright © 2020-2023  润新知