zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    permission 文档 翻译 运行时权限
    TabLayout ViewPager Fragment 简介 案例 MD
    Log 日志工具类 保存到文件 MD
    OkHttp 官方wiki 翻译 MD
    Okhttp 简介 示例 MD
    OkHttp 官方Wiki之【使用案例】
    DialogPlus
    倒计时 总结 Timer Handler CountDownTimer RxJava MD
    RecyclerView 判断滑到底部 顶部 预加载 更多 分页 MD
    CSS3的媒体查询(Media Queries)与移动设备显示尺寸大全
  • 原文地址:https://www.cnblogs.com/yxg123123/p/6898443.html
Copyright © 2011-2022 走看看